[Lldb-commits] [lldb] Extending LLDB to work on AIX (PR #102601)
Dhruv Srivastava via lldb-commits
lldb-commits at lists.llvm.org
Thu Jun 12 23:55:44 PDT 2025
https://github.com/DhruvSrivastavaX updated https://github.com/llvm/llvm-project/pull/102601
>From 39d395f75c306a0d932a783eef039fd93d66e246 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Wed, 7 Aug 2024 12:10:43 -0500
Subject: [PATCH 01/55] 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 30f3911a8b03c..fc91981db68c1 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 59cdc4593463c..2e9ae0d0b3221 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 a60921990cf77..a0f118a11984c 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 5589c1c9a350d..3829386562795 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<Module>,
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 4cbbbfa8a26e1..4fe06412b6b0b 100644
--- a/lldb/include/lldb/Core/ModuleSpec.h
+++ b/lldb/include/lldb/Core/ModuleSpec.h
@@ -21,6 +21,7 @@
#include <mutex>
#include <vector>
+#include <string.h>
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 52cfdf4dbb89c..f450e561d6afb 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 <getopt.h>
#include <unistd.h>
diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h
index b7010d69d88e7..156df8cf6901d 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 705aad559f3b7..29e6acf39bfb2 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 da0f9cd7aa8c0..cf359f7726d5d 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 <libxml/xmlreader.h>
#endif
diff --git a/lldb/include/lldb/Host/aix/AbstractSocket.h b/lldb/include/lldb/Host/aix/AbstractSocket.h
new file mode 100644
index 0000000000000..78a567a6b9095
--- /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 0000000000000..1e3487752995f
--- /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 <optional>
+
+namespace lldb_private {
+
+// Get PID (i.e. the primary thread ID) corresponding to the specified TID.
+std::optional<lldb::pid_t> 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 0000000000000..ced4cf34d38a8
--- /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 <string>
+
+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<std::string> 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 0000000000000..88928f18102d7
--- /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 <sys/ptrace.h>
+
+#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 0000000000000..27d6c2b50a35b
--- /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 <memory>
+
+namespace lldb_private {
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file);
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+getProcFile(::pid_t pid, const llvm::Twine &file);
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+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 0000000000000..acf79ecc6a1d0
--- /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 <sys/uio.h>
+
+// 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 3fb9add479541..ebb475bfaf6b8 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 8592323322e38..bf66ccec263d2 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<ObjectFile>,
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 7b646d743346b..281a89951ef88 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<lldb::addr_t> 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<lldb::addr_t> 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 0629e2faae7e9..7dccd317c2dca 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 cf16fbc812aa4..886ca766112c8 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 <typename B, typename S> struct Range;
@@ -1915,6 +1919,10 @@ class Process : public std::enable_shared_from_this<Process>,
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 ef8ae88403866..00a95853800ed 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 cb6e7caebb4ad..7880db1592e04 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<lldb::addr_t> args,
const EvaluateExpressionOptions &options);
+ ThreadPlanCallFunction(Thread &thread, const Address &function,
+ const Address &toc,
+ const CompilerType &return_type,
+ llvm::ArrayRef<lldb::addr_t> 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 dd468ef5bddef..9953bd6c24588 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 c24a3538f58da..98c1e956bf8f7 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 a32bc58507d8e..3ecdb11daef7d 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 3d908047f9455..728fe04d14d92 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<std::recursive_mutex> guard(
diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp
index 75b66364d4f1a..fad9a4076a54f 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<std::recursive_mutex> guard(
diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp
index 7f63aaf6fa7d5..5c7c0a8f6504b 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 7758a87403b5a..ea43a7f98b69f 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 387c4fac6b0f8..43c5b043ef7a2 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 f9d7832254f46..044a5d29978e8 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 0763e88d4608f..9ed55853930a6 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 444e44b392891..c1feec990f989 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 c2e091ee8555b..5374b16881950 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 0000000000000..bfb67d452f7ec
--- /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 0000000000000..d82cb9049d389
--- /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 <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#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 <sstream>
+#include <sys/procfs.h>
+
+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<ProcessState>(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<llvm::MemoryBuffer> 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<llvm::MemoryBuffer> 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::pid_t> 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 0000000000000..8bda09e01741b
--- /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 <climits>
+#include <cstdio>
+#include <cstring>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <mutex>
+
+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<std::string> 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 0000000000000..1bf2662190127
--- /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<std::unique_ptr<llvm::MemoryBuffer>>
+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<std::unique_ptr<llvm::MemoryBuffer>>
+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<std::unique_ptr<llvm::MemoryBuffer>>
+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 c2044b6873221..e0ae2aa1774b3 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 e03d36e9cad4a..2fd7111a94fb2 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 <stdio.h>
+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 <sys/ldr.h>
+#include <errno.h>
+
+/* 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<void *>(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 0000000000000..9601ab43575f9
--- /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 at 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 at cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay at 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 at 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 at 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 at 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 f480ef3166a44..62cac78aaac23 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 fceeff08ed9d3..143254bb12901 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<NativeFile>(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 cdb76da626bc9..a7c50f6a3c835 100644
--- a/lldb/source/Host/posix/FileSystemPosix.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
@@ -11,7 +11,9 @@
// C includes
#include <dirent.h>
#include <fcntl.h>
+#if !defined(__AIX__)
#include <sys/mount.h>
+#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp
index 5fe4d015251c8..e5be0db4cf19b 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 0a832ebad13a7..cd106f605b1f4 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 c1a167826f76f..9f94830c8509f 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 1a172a95aa147..4b01442a94bac 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 eac058701313b..feb0d7c0e09be 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<addr_t> 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<uint64_t>(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<uint64_t>(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<uint64_t> 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 bfa96cc0df703..d752a8ded9748 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<lldb::addr_t> 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<lldb::addr_t> 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 0000000000000..02fe0d617955a
--- /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 0000000000000..62663974134b0
--- /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 <sys/ldr.h>
+#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 0000000000000..ae4b7aca66dcc
--- /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 <map>
+
+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<lldb::ModuleSP, lldb::addr_t> 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 30607159acdc0..4f3fb693faae1 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 20e5652c65bf8..26abea0fdd24d 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 3863b6b3520db..624848dee6ec3 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 3035c51341778..d14ae2daeb47d 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 a9424f16b0ad0..1576c9700e557 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 b7cd2b1ac6bf6..876e74056face 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 b2781aa5e7db1..7a827a3ea76f9 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 1c58922e8d36c..de9719ad4a89e 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 1688fb27430a7..690fb0d60a09a 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 341923108e321..fb5bc2c58e6fb 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 6efd2516578ff..fe6c5a0544be3 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 7aa5b8d81890a..5ea55772c3aba 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 0000000000000..612a36265b536
--- /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 0000000000000..050ad73f1d19a
--- /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 "!<arch>\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 <ar.h>
+#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<llvm::StringRef> childNameOrErr = child.getName();
+ if (!childNameOrErr)
+ continue;
+ obj.ar_name.SetCString(childNameOrErr->str().c_str());
+ llvm::Expected<llvm::sys::TimePoint<std::chrono::seconds>> lastModifiedOrErr = child.getLastModified();
+ if (!lastModifiedOrErr)
+ continue;
+ obj.modification_time = (uint32_t)llvm::sys::toTimeT(*(lastModifiedOrErr));
+ llvm::Expected<unsigned> getUIDOrErr = child.getUID();
+ if (!getUIDOrErr)
+ continue;
+ obj.uid = (uint16_t)*getUIDOrErr;
+ llvm::Expected<unsigned> getGIDOrErr = child.getGID();
+ if (!getGIDOrErr)
+ continue;
+ obj.gid = (uint16_t)*getGIDOrErr;
+ llvm::Expected<llvm::sys::fs::perms> getAccessModeOrErr = child.getAccessMode();
+ if (!getAccessModeOrErr)
+ continue;
+ obj.mode = (uint16_t)*getAccessModeOrErr;
+ llvm::Expected<uint64_t> getRawSizeOrErr = child.getRawSize();
+ if (!getRawSizeOrErr)
+ continue;
+ obj.size = (uint32_t)*getRawSizeOrErr;
+
+ obj.file_offset = (lldb::offset_t)child.getDataOffset();
+
+ llvm::Expected<uint64_t> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<const void *>(file), static_cast<uint64_t>(file_offset),
+ static_cast<uint64_t>(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<ObjectContainerBigArchive> 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<ObjectContainerBigArchive> 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 0000000000000..ad9b814048a87
--- /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 <map>
+#include <memory>
+#include <mutex>
+
+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<Archive> shared_ptr;
+ typedef std::multimap<lldb_private::FileSpec, shared_ptr> 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<uint32_t> ObjectNameToIndexMap;
+ // Member Variables
+ lldb_private::ArchSpec m_arch;
+ llvm::sys::TimePoint<> m_modification_time;
+ lldb::offset_t m_file_offset;
+ std::vector<Object> 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 cda0c8151dd8a..2492798bb13ef 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 773241c8944c8..7abd0c96f4fd7 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 ce095bcc48374..bcb6330cbb1f9 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<tid_t> &tids) {
+bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector<lldb::tid_t> &tids) {
tids.clear();
ModuleSP module_sp(GetModule());
if (module_sp) {
@@ -5724,8 +5724,8 @@ bool ObjectFileMachO::GetCorefileThreadExtraInfos(std::vector<tid_t> &tids) {
return false;
}
StructuredData::Dictionary *thread = *maybe_thread;
- tid_t tid = LLDB_INVALID_THREAD_ID;
- if (thread->GetValueForKeyAsInteger<tid_t>("thread_id", tid))
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ if (thread->GetValueForKeyAsInteger<lldb::tid_t>("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 faa144bfb5f6a..d27cdfc60de85 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 f0832dbf07347..75cc54e4f0d48 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<PDBFile> 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 bda691ade8af0..db8fa78043fdc 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<llvm::object::COFFObjectFile>(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 0000000000000..8840248574c88
--- /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 0000000000000..a4d9ea295b4c3
--- /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 <algorithm>
+#include <cassert>
+#include <unordered_map>
+#include <string.h>
+
+#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<ObjectFileXCOFF>(
+ 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<llvm::object::XCOFFObjectFile>(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<std::recursive_mutex> 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<DataBufferHeap>(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<StringRef> 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<llvm::object::SymbolRef::Type> 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<SectionList>();
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ std::lock_guard<std::recursive_mutex> 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<lldb::offset_t>(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<SectionType>(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<FileSpec> ObjectFileXCOFF::GetDebugLink() {
+ return std::nullopt;
+}
+
+uint32_t ObjectFileXCOFF::ParseDependentModules() {
+ ModuleSP module_sp(GetModule());
+ if (!module_sp)
+ return 0;
+
+ std::lock_guard<std::recursive_mutex> 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<std::string, std::vector<std::string>>::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<std::string>();
+ 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<ObjectFile::LoadableData>
+ObjectFileXCOFF::GetLoadableData(Target &target) {
+ std::vector<LoadableData> 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 0000000000000..5a12d16886489
--- /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 <cstdint>
+
+#include <vector>
+
+#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<lldb_private::FileSpec> 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<LoadableData>
+ 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<section_header_t> 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<llvm::object::XCOFFObjectFile> m_binary;
+ lldb_private::Address m_entry_point_address;
+ std::optional<lldb_private::FileSpecList> m_deps_filespec;
+ std::map<std::string, std::vector<std::string>> 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 e026ffefd645e..106e38b6e25ae 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<bool> &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 0000000000000..85ff0a315eabd
--- /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 0000000000000..b6b08b73bec41
--- /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 <cstdio>
+#if LLDB_ENABLE_POSIX
+#include <sys/utsname.h>
+#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 <sys/mman.h>
+#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() : "<null>",
+ arch ? arch->GetTriple().getTriple() : "<null>");
+
+ 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<ArchSpec>
+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<UnwindPlan::Row>();
+ 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<UnwindPlan>(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 0000000000000..3ae8089a48d71
--- /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<ArchSpec>
+ 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<ArchSpec> m_supported_architectures;
+
+private:
+ std::unique_ptr<TypeSystemClang> 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 6869587f917eb..9d0afd97cff85 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 0000000000000..e9d83266f5857
--- /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 0000000000000..882f20d30a3bf
--- /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 <cerrno>
+#include <cstdint>
+#include <cstring>
+#include <unistd.h>
+
+#include <fstream>
+#include <mutex>
+#include <optional>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+
+#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 <sys/reg.h>
+#include <sys/ptrace.h>
+#include <sys/ldr.h>
+#include <sys/socket.h>
+//#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <sys/mman.h>
+
+#ifdef __aarch64__
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#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<uint32_t>(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<int> 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<std::unique_ptr<NativeProcessProtocol>>
+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<StringError>("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<StringError>("Cannot get process architectrue",
+ llvm::inconvertibleErrorCode());
+ }
+ /*llvm::Expected<ArchSpec> 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<NativeProcessAIX>(new NativeProcessAIX(
+ pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
+ Info.GetArchitecture(), *this, {pid}));
+}
+
+llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+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<StringError>("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<ArchSpec> arch_or =
+ NativeRegisterContextAIX::DetermineArchitecture(tids[0]);
+ if (!arch_or)
+ return arch_or.takeError();
+#endif
+
+ return std::unique_ptr<NativeProcessAIX>(
+ 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<std::pair<lldb::pid_t, WaitStatus>> 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<std::vector<::pid_t>> 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<NativeProcessAIX> 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<NativeThreadAIX &>(*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<NativeThreadAIX &>(*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<MemoryRegionInfo> 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<uint64_t>
+NativeProcessAIX::Syscall(llvm::ArrayRef<uint64_t> 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<uint8_t, 8> 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<addr_t>
+NativeProcessAIX::AllocateMemory(size_t size, uint32_t permissions) {
+
+ std::optional<NativeRegisterContextAIX::MmapData> mmap_data =
+ GetCurrentThread()->GetRegisterContext().GetMmapData();
+ if (!mmap_data)
+ return llvm::make_error<UnimplementedError>();
+
+ 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<uint64_t> 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<NativeRegisterContextAIX::MmapData> mmap_data =
+ GetCurrentThread()->GetRegisterContext().GetMmapData();
+ if (!mmap_data)
+ return llvm::make_error<UnimplementedError>();
+
+ 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<uint64_t> 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<uint8_t> &tags) {
+ llvm::Expected<NativeRegisterContextAIX::MemoryTaggingDetails> 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<void *>(read_addr), static_cast<void *>(&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<uint8_t> &tags) {
+ llvm::Expected<NativeRegisterContextAIX::MemoryTaggingDetails> 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<std::vector<lldb::addr_t>> unpacked_tags_or_err =
+ details->manager->UnpackTagsData(tags);
+ if (!unpacked_tags_or_err)
+ return Status(unpacked_tags_or_err.takeError());
+
+ llvm::Expected<std::vector<lldb::addr_t>> 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<std::vector<uint8_t>> 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<void *>(write_addr), static_cast<void *>(&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<llvm::ArrayRef<uint8_t>>
+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<unsigned char *>(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<const unsigned char *>(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<NativeThreadAIX>(*this, thread_id));
+ NativeThreadAIX &thread =
+ static_cast<NativeThreadAIX &>(*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<NativeThreadAIX *>(
+ NativeProcessProtocol::GetThreadByID(tid));
+}
+
+NativeThreadAIX *NativeProcessAIX::GetCurrentThread() {
+ return static_cast<NativeThreadAIX *>(
+ 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<NativeThreadAIX *>(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<uint64_t>(val);
+}
+
+static void SetRegister(lldb::pid_t pid, long long addr, void *buf) {
+ uint64_t val = llvm::byteswap<uint64_t>(*(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<uint64_t>(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<uint64_t>(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<uint64_t>(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<TraceSupportedResponse> 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<json::Value> NativeProcessAIX::TraceGetState(StringRef type) {
+ return NativeProcessProtocol::TraceGetState(type);
+}
+
+Expected<std::vector<uint8_t>> 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 0000000000000..bdb6f7c500885
--- /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 <csignal>
+#include <unordered_set>
+
+#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<std::unique_ptr<NativeProcessProtocol>>
+ Launch(ProcessLaunchInfo &launch_info,
+ NativeDelegate &native_delegate) override;
+
+ llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
+ 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<NativeProcessAIX *, 2> 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<lldb::addr_t> 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<uint8_t> &tags) override;
+
+ Status WriteMemoryTags(int32_t type, lldb::addr_t addr, size_t len,
+ const std::vector<uint8_t> &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<std::unique_ptr<llvm::MemoryBuffer>>
+ 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<llvm::json::Value>
+ TraceGetState(llvm::StringRef type) override;
+
+ llvm::Expected<std::vector<uint8_t>>
+ TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override;
+
+ llvm::Expected<TraceSupportedResponse> 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<llvm::ArrayRef<uint8_t>>
+ GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
+
+ llvm::Expected<uint64_t> Syscall(llvm::ArrayRef<uint64_t> 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<std::pair<MemoryRegionInfo, FileSpec>> 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<lldb::addr_t, lldb::addr_t> 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<std::vector<::pid_t>> 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 0000000000000..0859f9501c1b6
--- /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<void *>(®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<void *>(®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<void *>(offset),
+ nullptr, 0, &data);
+
+ if (error.Success())
+ // First cast to an unsigned of the same size to avoid sign extension.
+ value.SetUInt(static_cast<unsigned long>(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<void *>(value.GetAsUInt64());
+ LLDB_LOG(log, "{0}: {1}", reg_name, buf);
+
+ return NativeProcessAIX::PtraceWrapper(
+ PTRACE_POKEUSER, m_thread.GetID(), reinterpret_cast<void *>(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 0000000000000..9c2a326856c0b
--- /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<NativeRegisterContextAIX>
+ 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<uint8_t> Insn;
+
+ /// Registers used for syscall arguments. The first register is used to
+ /// store the syscall number.
+ llvm::ArrayRef<uint32_t> 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<SyscallData> 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<MmapData> 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<MemoryTagManager> 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<MemoryTaggingDetails>
+ 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 0000000000000..1996373791748
--- /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 <sys/socket.h>
+#include <sys/reg.h>
+#include <sys/ptrace.h>
+#include <sys/ldr.h>
+
+#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>
+NativeRegisterContextAIX::CreateHostNativeRegisterContextAIX(
+ const ArchSpec &target_arch, NativeThreadAIX &native_thread) {
+ switch (target_arch.GetMachine()) {
+ case llvm::Triple::ppc64:
+ return std::make_unique<NativeRegisterContextAIX_ppc64>(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
+ : "<unknown register>");
+
+ 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>(*(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<uint32_t>(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<long *>(m_hwp_regs[wp_index].slot);
+
+ // Update watchpoint in local cache
+ m_hwp_regs[wp_index].control &= llvm::maskTrailingZeros<uint32_t>(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<long>(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 0000000000000..a29f786f2313a
--- /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<DREG, 4> 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 0000000000000..e07daccdff550
--- /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 <csignal>
+#include <sstream>
+
+#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 <sys/types.h>
+#include <sys/ptrace.h>
+#include <signal.h>
+
+#if 0
+#include <sys/syscall.h>
+// 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<uint32_t>(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<void *>(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<void *>(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: <addr>)
+ // Remove the closing )
+ m_stop_description.pop_back();
+
+ std::stringstream ss;
+ lldb::addr_t fault_addr = reinterpret_cast<uintptr_t>(info->si_addr);
+ std::unique_ptr<MemoryTagManager> manager(std::move(details->manager));
+
+ ss << " logical tag: 0x" << std::hex << manager->GetLogicalTag(fault_addr);
+
+ std::vector<uint8_t> 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<std::vector<lldb::addr_t>> 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<NativeProcessAIX &>(m_process);
+}
+
+const NativeProcessAIX &NativeThreadAIX::GetProcess() const {
+ return static_cast<const NativeProcessAIX &>(m_process);
+}
+
+llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
+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 0000000000000..706a7ce69da8e
--- /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 <csignal>
+#include <map>
+#include <memory>
+#include <string>
+
+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<std::unique_ptr<llvm::MemoryBuffer>>
+ 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<NativeRegisterContextAIX> m_reg_context_up;
+ std::string m_stop_description;
+ using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
+ 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 a51d0f7afd175..01bb5f462eba4 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 32c71d87c7f58..db271357d792a 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 159fd2856443c..d9b41d595147f 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<uint32_t>(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 89ecc757a68f5..550b53688fd39 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 6755999b18185..4eddbb5ec4cfd 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 74e392249a94e..b7ecf7a5dc328 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 <sys/ldr.h>
+#endif
+
#if defined(HAVE_LIBCOMPRESSION)
#include <compression.h>
#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<uint8_t> 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 898d176abc346..520f37ac56716 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<uint32_t> GetWatchpointSlotCount();
+#if defined(__AIX__)
+ Status GetLDXINFO(struct ld_xinfo *info_ptr);
+#endif
std::optional<bool> GetWatchpointReportedAfter();
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index a0b08a219ae14..f019062986925 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 <sys/ldr.h>
+#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 646b6a102abf6..a464479e178de 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 6f9c2cc1e4b4e..10fbaa2b3c837 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 <sys/ldr.h>
+#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<uint32_t> 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 2492795851388..82200fbea21cd 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 1da7696c9a352..930c707604bb3 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<tid_t> used_tids;
+ std::set<lldb::tid_t> used_tids;
const uint32_t num_threads = core_objfile->GetNumThreadContexts();
- std::vector<tid_t> tids;
+ std::vector<lldb::tid_t> 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 7523d65abf0f8..1ce60a0b66154 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 e1f73f1997e36..92882cfc3da31 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<DWARFUnit *, uint64_t>
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 66a762bf9b685..6721c1895a576 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<DWARFUnitSP>
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<uint64_t>
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 2064b73dc3ea5..824528fc3acfa 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 f3df8a2c27f5a..de244e372579d 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 110b5c86fc425..6df03533cda29 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<lldb::addr_t> 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 a42c44b761dc5..833489b16dfd7 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 e3c4f2ee398cc..e31245178b2f2 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 <sys/ldr.h>
+#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 a61228d092d89..57f42ea56cb18 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -40,6 +40,9 @@
#include <cassert>
#include <memory>
+#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 50dcb66b9719f..0926579ea2930 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<addr_t> 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 f43e940492b09..255b829738ba2 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 07ef435ef451d..3868f77169cc6 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 9f79d2271b1e6..dbd3236536f8c 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 5ac474736eb63..413a1e5120288 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 9dd0413be14cf..5ed61ad33ffc4 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 e6d6e56fc9203..2ead258719f32 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 cd304a047dea6..78617be24f780 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 14371da64f2f2..f7eaf56738d7d 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 f8f0d86453f58..2fa6f6c9a5369 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 9030ed709a647..0d69ae32a008f 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 4233252a84dfc..91bb2083a88b5 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 563284730bc70..2a14f4f9c82aa 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 58887f6b2467e..89d0f5b87171a 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<std::unique_ptr<vfs::File>>
- openFileForRead(const Twine &Path) override {
+ openFileForRead(const Twine &Path, bool IsText) override {
auto S = status(Path);
if (S)
return std::unique_ptr<vfs::File>(new DummyFile{*S});
diff --git a/lldb/unittests/Host/posix/TerminalTest.cpp b/lldb/unittests/Host/posix/TerminalTest.cpp
index 5187a0c20a68b..f3de92c0852b1 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<speed_t>(B38400));
EXPECT_EQ(cfgetospeed(&terminfo), static_cast<speed_t>(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<speed_t>(B115200));
EXPECT_EQ(cfgetospeed(&terminfo), static_cast<speed_t>(B115200));
+#endif
// uncommon value
#if defined(B153600)
diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index 5a7cd8e38f2b7..fa9c6781e24f5 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -542,7 +542,6 @@ class XCOFFObjectFile : public ObjectFile {
template <typename T> 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<uintptr_t> getLoaderSectionAddress() const;
+
static constexpr uint64_t InvalidRelocOffset =
std::numeric_limits<uint64_t>::max();
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index bdd04b00f557b..9c96df1bbdc54 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -251,10 +251,16 @@ Expected<uint64_t> 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 <dhruv.srivastava at ibm.com>
Date: Wed, 7 Aug 2024 12:18:45 -0500
Subject: [PATCH 02/55] 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 0000000000000..d814272967476
--- /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 <dhruv.srivastava at ibm.com>
Date: Wed, 7 Aug 2024 13:27:20 -0500
Subject: [PATCH 03/55] 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 5ed61ad33ffc4..9dd0413be14cf 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 2ead258719f32..e6d6e56fc9203 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 <lakshmi at aixbase.aus.stglabs.ibm.com>
Date: Thu, 22 Aug 2024 08:49:50 -0500
Subject: [PATCH 04/55] 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 89d0f5b87171a..58887f6b2467e 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<std::unique_ptr<vfs::File>>
- openFileForRead(const Twine &Path, bool IsText) override {
+ openFileForRead(const Twine &Path) override {
auto S = status(Path);
if (S)
return std::unique_ptr<vfs::File>(new DummyFile{*S});
>From 758ab642d0974e799ac902d8ad240a3a90aeb24d Mon Sep 17 00:00:00 2001
From: Lakshmi Surekha Kovvuri <lakshmi at aixbase.aus.stglabs.ibm.com>
Date: Fri, 30 Aug 2024 08:33:32 -0500
Subject: [PATCH 05/55] 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 882f20d30a3bf..5b01a66b0453f 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<NativeThreadAIX &>(*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 0859f9501c1b6..071e55543cc3c 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 1996373791748..0132b52dec6f2 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
: "<unknown register>");
@@ -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 e07daccdff550..bb14b6ab4a05e 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 17926f8e4ab53..0aa68a4a09cbe 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<uint8_t> 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 <dhruv.srivastava at ibm.com>
Date: Tue, 10 Sep 2024 02:00:09 -0500
Subject: [PATCH 06/55] 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 88928f18102d7..393928a89add3 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 <lakshmi at aixbase.aus.stglabs.ibm.com>
Date: Wed, 11 Sep 2024 02:52:41 -0500
Subject: [PATCH 07/55] 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 4084e90782fd5..9e92ec1470d4d 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 506f3d225a21e..c1013aa7a7e4e 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 <lakshmi at aixbase.aus.stglabs.ibm.com>
Date: Thu, 12 Sep 2024 13:22:03 -0500
Subject: [PATCH 08/55] 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 5b01a66b0453f..fc84763857453 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<NativeRegisterContextAIX::MemoryTaggingDetails> 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<NativeRegisterContextAIX::MemoryTaggingDetails> 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<std::vector<lldb::addr_t>> 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<std::vector<lldb::addr_t>> 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<std::vector<uint8_t>> 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 <Lakshmi.Kovvuri at ibm.com>
Date: Fri, 13 Sep 2024 16:25:47 +0530
Subject: [PATCH 09/55] 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 393928a89add3..88928f18102d7 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 <dhruv.srivastava at ibm.com>
Date: Thu, 10 Oct 2024 00:38:18 -0500
Subject: [PATCH 10/55] 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 22fb34b8419c5..0931d905a9749 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 2e9ae0d0b3221..a4fd8bccf056d 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 f450e561d6afb..b2b436e64a692 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 <getopt.h>
#include <unistd.h>
diff --git a/lldb/include/lldb/Host/HostInfo.h b/lldb/include/lldb/Host/HostInfo.h
index 156df8cf6901d..0f7ec0e0aa0d2 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 cf359f7726d5d..483589f1abc75 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 ebb475bfaf6b8..652e6174ff8b6 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 4a47ffd8d779d..d1527d316d678 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<Process>,
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 46c06cb422caf..b6176f8e5727f 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 43c5b043ef7a2..8f2e3562f6577 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 9ed55853930a6..e0a9f7fcc7135 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 94b1d0fd57d07..dc48cb87b5ce6 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 <stdio.h>
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<void *>(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 62cac78aaac23..fbc409105fe60 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 bd204c812b7e3..09c3fd2af6d3e 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 866fd8ac96c7b..21da5612ff6b8 100644
--- a/lldb/source/Host/posix/FileSystemPosix.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
@@ -11,7 +11,7 @@
// C includes
#include <dirent.h>
#include <fcntl.h>
-#if !defined(__AIX__)
+#if !defined(_AIX)
#include <sys/mount.h>
#endif
#include <sys/param.h>
diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp
index d1eba52791a78..015570236b9d3 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 b8a96fbd19f02..f9f99decd39c2 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 4b01442a94bac..2e2d622d9981c 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 88a82f4a0d20c..a3abb15ee625b 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 62663974134b0..7f3a638d5b028 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 <sys/ldr.h>
#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 1576c9700e557..d98b2880ca3b4 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 690fb0d60a09a..9a52fb2f2adc5 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 fb5bc2c58e6fb..71f2b127afb12 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 5ea55772c3aba..4f747ab20c9ef 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 050ad73f1d19a..38756a0dd2969 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 "!<arch>\n"
#define SARMAG 8
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp b/lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp
index d8834af2c33ef..9aab76c6c48ba 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 75cc54e4f0d48..d76d6adb1be2c 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<PDBFile> 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 519ce2ca4a0b2..02a86234bd363 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<llvm::object::COFFObjectFile>(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 b6b08b73bec41..5c94477002978 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 <sys/mman.h>
#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 db271357d792a..ea758caa653a1 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 443b7c7b2c7fb..fa0a3b5d4dc38 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 <sys/ldr.h>
#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 520f37ac56716..1812fc9b7ca65 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<uint32_t> 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 4f1ef0898ba08..27be61a474238 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 <sys/ldr.h>
#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 ca381290d0e9f..5b7ce5f1424d9 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 <sys/ldr.h>
#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 82200fbea21cd..2bf3a04d213d4 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 a9aef7ef21855..e6ae7fc559ef4 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 <sys/ldr.h>
#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 fbdbc8c63a5d0..fdf269a3d3653 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -40,7 +40,7 @@
#include <cassert>
#include <memory>
-#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 8edf359cac497..764bea5bf86c6 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 45837503e8b73..d17ed77485d31 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 91bb2083a88b5..52c2eae0c9033 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 844a6370bdb2e..dcbb421a73e25 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 c76476c947054..5c042261b9ef2 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 c1013aa7a7e4e..00ffd33d68f7a 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 f3de92c0852b1..64e6be64db80c 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<speed_t>(B38400));
EXPECT_EQ(cfgetospeed(&terminfo), static_cast<speed_t>(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<speed_t>(B115200));
>From a8020a6a8692f059679195ae1a0ef5e0eeee94c8 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Thu, 10 Oct 2024 04:52:08 -0500
Subject: [PATCH 11/55] Removed from lldb/CMakeLists
---
lldb/CMakeLists.txt | 4 ----
1 file changed, 4 deletions(-)
diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt
index a4fd8bccf056d..59cdc4593463c 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 <Lakshmi.Kovvuri at ibm.com>
Date: Thu, 14 Nov 2024 13:23:59 -0600
Subject: [PATCH 12/55] 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 395a126a01fce..a4d9ea295b4c3 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<std::recursive_mutex> 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<DataBufferHeap>(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<StringRef> 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 <dhruv.srivastava at ibm.com>
Date: Sun, 17 Nov 2024 00:15:01 -0600
Subject: [PATCH 13/55] 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 7f3a638d5b028..acaa6a72edded 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 <sys/ldr.h>
+#include <procinfo.h>
+#include <sys/procfs.h>
+#include <iostream>
+#include <fstream>
#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<char*>(&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<std::string> 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 ae4b7aca66dcc..0ffbe688e0069 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<lldb::ModuleSP, lldb::addr_t> m_loaded_modules;
};
>From 48b8b1b6532181acab0ee1710d5f4ab92903ae78 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 18 Nov 2024 02:56:31 -0600
Subject: [PATCH 14/55] 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 acaa6a72edded..1a98bb9334043 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<char*>(&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<std::string> 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 <Lakshmi.Kovvuri at ibm.com>
Date: Tue, 19 Nov 2024 09:44:42 -0600
Subject: [PATCH 15/55] 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 f68268f114075..4c617cdde67ba 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 <Lakshmi.Kovvuri at ibm.com>
Date: Thu, 5 Dec 2024 05:13:14 -0600
Subject: [PATCH 16/55] 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 78a567a6b9095..accfd01457a5e 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 bfb67d452f7ec..fddf78f54f46d 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 9a0b385d998bf..6cbffb2d9c4bd 100644
--- a/lldb/source/Host/posix/DomainSocket.cpp
+++ b/lldb/source/Host/posix/DomainSocket.cpp
@@ -17,6 +17,10 @@
#include <sys/socket.h>
#include <sys/un.h>
+#if defined(_AIX)
+#include <strings.h>
+#endif
+
using namespace lldb;
using namespace lldb_private;
>From 97531f7bf6e385f0f51d860c6eea17aeb32f6594 Mon Sep 17 00:00:00 2001
From: Lakshmi-Surekha <Lakshmi.Kovvuri at ibm.com>
Date: Thu, 19 Dec 2024 06:38:36 -0600
Subject: [PATCH 17/55] 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 395a126a01fce..a4d9ea295b4c3 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<std::recursive_mutex> 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<DataBufferHeap>(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<StringRef> 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 <dhruv.srivastava at ibm.com>
Date: Tue, 24 Dec 2024 02:05:35 -0600
Subject: [PATCH 18/55] 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 32d034e60d26c..e3d1300cf76ed 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<NativeFile>(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 6cbffb2d9c4bd..28db5964a5a8a 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 21da5612ff6b8..1a84f550662d7 100644
--- a/lldb/source/Host/posix/FileSystemPosix.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
@@ -11,7 +11,7 @@
// C includes
#include <dirent.h>
#include <fcntl.h>
-#if !defined(_AIX)
+#ifndef _AIX
#include <sys/mount.h>
#endif
#include <sys/param.h>
diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp
index 125b954023dc0..e4ff928a58962 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<MainLoopPosix::TimePoint> 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<MainLoopPosix::TimePoint> 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<milliseconds>(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 52fc58aa21bf4..7b8b42a4b7fe0 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 1d841a032aa6e..1d79edbede5d6 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 4f747ab20c9ef..b202898ff438a 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<llvm::MemoryBuffer> 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::seconds>(
std::chrono::time_point_cast<std::chrono::seconds>(
- 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 ac91183a271cc..85bb85044ec15 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 <dhruv.srivastava at ibm.com>
Date: Fri, 27 Dec 2024 06:50:27 -0600
Subject: [PATCH 19/55] 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 ced4cf34d38a8..ba727e1d5f171 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 <string>
-
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<std::string> 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 8bda09e01741b..ef07b07c8cab2 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<std::string> 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 a4d9ea295b4c3..afd8027bab06c 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 <algorithm>
-#include <cassert>
-#include <unordered_map>
-#include <string.h>
-
-#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 <algorithm>
+#include <cassert>
+#include <cstring>
+#include <unordered_map>
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<llvm::object::XCOFFObjectFile>(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<FileSpec> 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 5a12d16886489..f827fca3932f4 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 <cstdint>
-
-#include <vector>
-
#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 <cstdint>
+#include <vector>
/// \class ObjectFileXCOFF
/// Generic XCOFF object file reader.
@@ -240,4 +239,4 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
std::map<std::string, std::vector<std::string>> 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 <dhruv.srivastava at ibm.com>
Date: Sun, 5 Jan 2025 05:01:47 -0600
Subject: [PATCH 20/55] 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 ba727e1d5f171..5a52c42fa6199 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 ef07b07c8cab2..2996fcb55f811 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 <climits>
#include <cstdio>
#include <cstring>
#include <sys/utsname.h>
#include <unistd.h>
-
#include <algorithm>
#include <mutex>
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 <dhruv.srivastava at ibm.com>
Date: Sun, 5 Jan 2025 05:49:40 -0600
Subject: [PATCH 21/55] 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 2996fcb55f811..d09b9052668af 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 <dhruv.srivastava at ibm.com>
Date: Sun, 5 Jan 2025 15:35:23 -0600
Subject: [PATCH 22/55] 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 5a52c42fa6199..331a274630850 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 d09b9052668af..61b47462dd647 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 <climits>
-#include <cstdio>
-#include <cstring>
-#include <sys/utsname.h>
-#include <unistd.h>
-#include <algorithm>
-#include <mutex>
using namespace lldb_private;
>From cdc31f3963365e4595247ff5a7155662df1ce1af Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 6 Jan 2025 09:28:56 -0600
Subject: [PATCH 23/55] 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 f326bc07dc1f6..f4fca8acc4d83 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 <dhruv.srivastava at ibm.com>
Date: Mon, 6 Jan 2025 09:39:36 -0600
Subject: [PATCH 24/55] 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 f30e84d83efca..be8fcdf2c8f2c 100644
--- a/lldb/source/Host/posix/DomainSocket.cpp
+++ b/lldb/source/Host/posix/DomainSocket.cpp
@@ -17,10 +17,6 @@
#include <sys/socket.h>
#include <sys/un.h>
-#if defined(_AIX)
-#include <strings.h>
-#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 1a84f550662d7..a631bb01209ec 100644
--- a/lldb/source/Host/posix/FileSystemPosix.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
@@ -11,9 +11,6 @@
// C includes
#include <dirent.h>
#include <fcntl.h>
-#ifndef _AIX
-#include <sys/mount.h>
-#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
>From 0a706d29dabeefa62e354fc9358d650f89032048 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 6 Jan 2025 09:44:10 -0600
Subject: [PATCH 25/55] 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 a631bb01209ec..945e2affc8371 100644
--- a/lldb/source/Host/posix/FileSystemPosix.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
@@ -11,6 +11,7 @@
// C includes
#include <dirent.h>
#include <fcntl.h>
+#include <sys/mount.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
>From 84ebb4ec9b542c38fe1b60261a3253383e9fbf5d Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 6 Jan 2025 09:54:58 -0600
Subject: [PATCH 26/55] 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 945e2affc8371..1a84f550662d7 100644
--- a/lldb/source/Host/posix/FileSystemPosix.cpp
+++ b/lldb/source/Host/posix/FileSystemPosix.cpp
@@ -11,7 +11,9 @@
// C includes
#include <dirent.h>
#include <fcntl.h>
+#ifndef _AIX
#include <sys/mount.h>
+#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
>From 844f7980040de9e13620e9d65a3fcaef56b6c8d6 Mon Sep 17 00:00:00 2001
From: Dhruv Srivastava <dhruv.srivastava at ibm.com>
Date: Thu, 9 Jan 2025 09:47:43 +0530
Subject: [PATCH 27/55] 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 2530c8fa353ba..0ed2016667162 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<NativeFile>(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 <ravindrarshinde212 at ibm.com>
Date: Fri, 17 Jan 2025 13:58:13 +0530
Subject: [PATCH 28/55] [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 <ravindrarshinde212 at ibm.com>
---
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 f31ac381391b4..75f9c9c2e999c 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<Target>,
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<Target>,
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 afd8027bab06c..cf11e5fb8f5a3 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 <dhruv.srivastava at ibm.com>
Date: Sun, 19 Jan 2025 03:43:11 -0600
Subject: [PATCH 29/55] 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 eb348e2b97232..0a03e000c0cae 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 <dhruv.srivastava at ibm.com>
Date: Mon, 27 Jan 2025 06:35:19 -0600
Subject: [PATCH 30/55] 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 758e9f49ade2c..adf74df8aa90b 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<void *>(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 <Ravindra.Shinde2 at ibm.com>
Date: Tue, 4 Feb 2025 03:23:56 -0600
Subject: [PATCH 31/55] 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 <Ravindra.Shinde2 at ibm.com>
---
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 40ce76d70d6e8..b5bd68b8539bd 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -18,8 +18,12 @@
#include <netdb.h>
#include <pwd.h>
#include <sys/stat.h>
+
+#ifndef _AIX
#include <sys/syscall.h>
#include <sys/wait.h>
+#endif
+
#include <unistd.h>
#include <spawn.h>
#endif
>From 2644be59b13a61c69cc635875c94b0b4645fe76c Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 10 Feb 2025 01:49:12 -0600
Subject: [PATCH 32/55] InferiorCallPOSIX.cpp
---
lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index d1f9fe851119e..8e74cce097894 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -120,12 +120,13 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
arch, addr, length, prot_arg, flags, fd, offset);
#if defined(_AIX)
lldb::ThreadPlanSP call_plan_sp(
- new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(),
+ new ThreadPlanCallFunction(*thread, mmap_addr,
toc_range.GetBaseAddress(),
void_ptr_type, args, options));
#else
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(
*thread, mmap_addr, void_ptr_type, args, options));
+#endif
if (call_plan_sp) {
DiagnosticManager diagnostics;
>From 4805b13cba964b58def39a66ad4c4309a9b2c501 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Wed, 12 Feb 2025 07:33:04 -0600
Subject: [PATCH 33/55] Merge branch gh-101657
---
.../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 97 -------------------
.../AIX-DYLD/DynamicLoaderAIXDYLD.h | 5 +-
2 files changed, 1 insertion(+), 101 deletions(-)
diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
index 1a98bb9334043..375d879c7a995 100644
--- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
@@ -21,10 +21,6 @@
#include "llvm/Support/FileSystem.h"
#if defined(_AIX)
#include <sys/ldr.h>
-#include <procinfo.h>
-#include <sys/procfs.h>
-#include <iostream>
-#include <fstream>
#endif
/*#include "llvm/ADT/Triple.h"
@@ -137,107 +133,14 @@ bool DynamicLoaderAIXDYLD::NotifyBreakpointHit(
}
-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;
- }
-
- 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";
- std::ifstream file(proc_file, std::ios::binary);
- if(!file.is_open())
- LLDB_LOGF(log, "Error: Unable to access process info ");
-
- file.read(reinterpret_cast<char*>(&psinfo), sizeof(psinfo_t));
- if(!file)
- 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());
-
- 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 using process info : %s", resolved_path);
- path_resolved = true;
- }
- else
- LLDB_LOGF(log, "Realpath error: Unable to resolve. ");
- }
-
- executable_name = resolved_path;
- if(path_resolved == false) {
- 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, "Resolved path using command line arg %s",executable_name.c_str());
- }
- }
-
- LLDB_LOGF(log, "Executable Name %s",executable_name.c_str());
- process_info.SetExecutableFile(lldb_private::FileSpec(executable_name),
- true);
-
- 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 0ffbe688e0069..ae4b7aca66dcc 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 "aix-dyld"; }
+ static llvm::StringRef GetPluginNameStatic() { return "windows-dyld"; }
static llvm::StringRef GetPluginDescriptionStatic();
static DynamicLoader *CreateInstance(Process *process, bool force);
@@ -46,9 +46,6 @@ 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<lldb::ModuleSP, lldb::addr_t> m_loaded_modules;
};
>From cff574b36903e12385e5d6cddf4532ba279f47de Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Wed, 12 Feb 2025 07:52:04 -0600
Subject: [PATCH 34/55] Fix for Debugging Attach to AIX Process
---
.../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 97 +++++++++++++++++++
.../AIX-DYLD/DynamicLoaderAIXDYLD.h | 5 +-
2 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
index 375d879c7a995..1a98bb9334043 100644
--- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
@@ -21,6 +21,10 @@
#include "llvm/Support/FileSystem.h"
#if defined(_AIX)
#include <sys/ldr.h>
+#include <procinfo.h>
+#include <sys/procfs.h>
+#include <iostream>
+#include <fstream>
#endif
/*#include "llvm/ADT/Triple.h"
@@ -133,14 +137,107 @@ bool DynamicLoaderAIXDYLD::NotifyBreakpointHit(
}
+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;
+ }
+
+ 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";
+ std::ifstream file(proc_file, std::ios::binary);
+ if(!file.is_open())
+ LLDB_LOGF(log, "Error: Unable to access process info ");
+
+ file.read(reinterpret_cast<char*>(&psinfo), sizeof(psinfo_t));
+ if(!file)
+ 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());
+
+ 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 using process info : %s", resolved_path);
+ path_resolved = true;
+ }
+ else
+ LLDB_LOGF(log, "Realpath error: Unable to resolve. ");
+ }
+
+ executable_name = resolved_path;
+ if(path_resolved == false) {
+ 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, "Resolved path using command line arg %s",executable_name.c_str());
+ }
+ }
+
+ LLDB_LOGF(log, "Executable Name %s",executable_name.c_str());
+ process_info.SetExecutableFile(lldb_private::FileSpec(executable_name),
+ true);
+
+ 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 ae4b7aca66dcc..0ffbe688e0069 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<lldb::ModuleSP, lldb::addr_t> m_loaded_modules;
};
>From 303fa3bc078d7572702fb302726d4dd1bd13ddb2 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Fri, 21 Feb 2025 06:18:33 -0600
Subject: [PATCH 35/55] Merge branch 'llvm:main' into gh-101657
---
lldb/source/Plugins/Platform/CMakeLists.txt | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt
index f5b0dbdd5e0a9..0220e734b36d1 100644
--- a/lldb/source/Plugins/Platform/CMakeLists.txt
+++ b/lldb/source/Plugins/Platform/CMakeLists.txt
@@ -9,4 +9,3 @@ add_subdirectory(OpenBSD)
add_subdirectory(POSIX)
add_subdirectory(QemuUser)
add_subdirectory(Windows)
-add_subdirectory(AIX)
>From 6947dec02bb527f710c1bea3827b2c16d89f308a Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Fri, 21 Feb 2025 07:02:53 -0600
Subject: [PATCH 36/55] Merge branch 'llvm:main' into gh-101657
---
.../Plugins/Platform/AIX/PlatformAIX.cpp | 171 +-----------------
1 file changed, 1 insertion(+), 170 deletions(-)
diff --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
index 0d66325d16267..21724d83133e9 100644
--- a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
+++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
@@ -130,12 +130,6 @@ void PlatformAIX::GetStatus(Stream &strm) {
#endif
}
-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"));
-}
-
void PlatformAIX::CalculateTrapHandlerSymbolNames() {}
lldb::UnwindPlanSP
@@ -160,168 +154,5 @@ MmapArgList PlatformAIX::GetMmapArgumentList(const ArchSpec &arch, addr_t addr,
}
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;
+ return CompilerType();
}
>From 24615119addcdf9fe5a8c5b2ebd0c15d75651279 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Sat, 22 Feb 2025 03:42:26 -0600
Subject: [PATCH 37/55] Removed un-needed changes
---
lldb/include/lldb/Host/aix/AbstractSocket.h | 25 ---------------------
lldb/include/lldb/Host/aix/Uio.h | 23 -------------------
lldb/source/Host/CMakeLists.txt | 1 -
lldb/source/Host/aix/AbstractSocket.cpp | 20 -----------------
4 files changed, 69 deletions(-)
delete mode 100644 lldb/include/lldb/Host/aix/AbstractSocket.h
delete mode 100644 lldb/include/lldb/Host/aix/Uio.h
delete mode 100644 lldb/source/Host/aix/AbstractSocket.cpp
diff --git a/lldb/include/lldb/Host/aix/AbstractSocket.h b/lldb/include/lldb/Host/aix/AbstractSocket.h
deleted file mode 100644
index accfd01457a5e..0000000000000
--- a/lldb/include/lldb/Host/aix/AbstractSocket.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//===-- 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();
-
-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/Uio.h b/lldb/include/lldb/Host/aix/Uio.h
deleted file mode 100644
index acf79ecc6a1d0..0000000000000
--- a/lldb/include/lldb/Host/aix/Uio.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//===-- 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 <sys/uio.h>
-
-// 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/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt
index bb6b5befa16e4..5a14b4c629825 100644
--- a/lldb/source/Host/CMakeLists.txt
+++ b/lldb/source/Host/CMakeLists.txt
@@ -140,7 +140,6 @@ else()
elseif (CMAKE_SYSTEM_NAME MATCHES "AIX")
add_host_subdirectory(aix
- aix/AbstractSocket.cpp
aix/Host.cpp
aix/HostInfoAIX.cpp
aix/Support.cpp
diff --git a/lldb/source/Host/aix/AbstractSocket.cpp b/lldb/source/Host/aix/AbstractSocket.cpp
deleted file mode 100644
index fddf78f54f46d..0000000000000
--- a/lldb/source/Host/aix/AbstractSocket.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-//===-- 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() : DomainSocket(ProtocolUnixAbstract) {}
-
-size_t AbstractSocket::GetNameOffset() const { return 1; }
-
-void AbstractSocket::DeleteSocketFile(llvm::StringRef name) {}
>From 25bea9ca48dc458c1dddd72f10a483e76926a04e Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Wed, 26 Feb 2025 01:10:15 -0600
Subject: [PATCH 38/55] Resolving coredump issue while attach with library
calls
---
lldb/include/lldb/Core/ModuleSpec.h | 2 ++
lldb/source/Core/ModuleList.cpp | 12 +++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb/include/lldb/Core/ModuleSpec.h
index 4fe06412b6b0b..9d79992b48c7e 100644
--- a/lldb/include/lldb/Core/ModuleSpec.h
+++ b/lldb/include/lldb/Core/ModuleSpec.h
@@ -122,6 +122,8 @@ class ModuleSpec {
ConstString &GetObjectName() { return m_object_name; }
ConstString GetObjectName() const { return m_object_name; }
+
+ void SetObjectName(ConstString objName) { m_object_name = objName; }
uint64_t GetObjectOffset() const { return m_object_offset; }
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 2b8ccab2406c6..862a2729c1afb 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -260,7 +260,17 @@ void ModuleList::ReplaceEquivalent(
module_sp->GetArchitecture());
equivalent_module_spec.GetPlatformFileSpec() =
module_sp->GetPlatformFileSpec();
-
+#ifdef _AIX
+ // To remove the exact equivalent module, the object name must be
+ // specified. When the equivalent_module_spec object is created, its
+ // object name is initially set to NULL. This is because the module_sp's
+ // GetPath() returns a path in the format (/usr/ccs/libc.a), which does
+ // not include the object name. As a result, MatchesModuleSpec may return
+ // true even though the object name is NULL and doesn't match any loaded
+ // module. To fix this, set the object name of the equivalent_module_spec
+ // to be the same as the object name of the module_sp. */
+ equivalent_module_spec.SetObjectName(module_sp->GetObjectName());
+#endif
size_t idx = 0;
while (idx < m_modules.size()) {
ModuleSP test_module_sp(m_modules[idx]);
>From 349ec0064668a0ee1d3af7c2f38fa7427b4b2d36 Mon Sep 17 00:00:00 2001
From: Dhruv Srivastava <dhruv.srivastava at ibm.com>
Date: Fri, 28 Feb 2025 23:44:40 +0530
Subject: [PATCH 39/55] [AIX][Coredump] AIX Coredump debugging Implementation
(#25)
Creates a general framework to be able to debug an AIX generated coredump file.
At this point, we are only supporting 64-bit core files using this general framework.
With this implementation, LLDB can recognise and debug any 64-bit AIX coredump file.
Most of the generic debugging commands work after this:
# bin/lldb --core /home/dhruv/LLDB/tests/core
(lldb) target create --core "/home/dhruv/LLDB/tests/core"
Core file '/home/dhruv/LLDB/tests/core' (powerpc64) was loaded.
(lldb) bt
* thread #1, stop reason = SIGSEGV
* frame #0: 0x0000000100000940 coretest64`main at core.c:5
frame #1: 0x00000001000004ac coretest64`__start + 116
(lldb) process status
Process 18446744071562067991 stopped
* thread #1, stop reason = SIGSEGV
frame #0: 0x0000000100000940 coretest64`main at core.c:5
2 char *str;
3 int a = 10;
4 str = "GfG";
-> 5 *(str+1) = 'n';
6 return a;
7 }
And others like memory read, image list, image dump sections, disassembly etc
---
.../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 62 ++++-
.../AIX-DYLD/DynamicLoaderAIXDYLD.h | 6 +
.../Plugins/ObjectFile/AIXCore/CMakeLists.txt | 13 +
.../ObjectFile/AIXCore/ObjectFileAIXCore.cpp | 254 ++++++++++++++++++
.../ObjectFile/AIXCore/ObjectFileAIXCore.h | 121 +++++++++
lldb/source/Plugins/ObjectFile/CMakeLists.txt | 1 +
lldb/source/Plugins/Process/CMakeLists.txt | 1 +
.../Plugins/Process/aix-core/AIXCore.cpp | 116 ++++++++
.../source/Plugins/Process/aix-core/AIXCore.h | 125 +++++++++
.../Plugins/Process/aix-core/CMakeLists.txt | 16 ++
.../Process/aix-core/ProcessAIXCore.cpp | 251 +++++++++++++++++
.../Plugins/Process/aix-core/ProcessAIXCore.h | 100 +++++++
.../aix-core/RegisterContextCoreAIX_ppc64.cpp | 136 ++++++++++
.../aix-core/RegisterContextCoreAIX_ppc64.h | 46 ++++
.../Process/aix-core/ThreadAIXCore.cpp | 127 +++++++++
.../Plugins/Process/aix-core/ThreadAIXCore.h | 110 ++++++++
16 files changed, 1484 insertions(+), 1 deletion(-)
create mode 100644 lldb/source/Plugins/ObjectFile/AIXCore/CMakeLists.txt
create mode 100644 lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp
create mode 100644 lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.h
create mode 100644 lldb/source/Plugins/Process/aix-core/AIXCore.cpp
create mode 100644 lldb/source/Plugins/Process/aix-core/AIXCore.h
create mode 100644 lldb/source/Plugins/Process/aix-core/CMakeLists.txt
create mode 100644 lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
create mode 100644 lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h
create mode 100644 lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.cpp
create mode 100644 lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.h
create mode 100644 lldb/source/Plugins/Process/aix-core/ThreadAIXCore.cpp
create mode 100644 lldb/source/Plugins/Process/aix-core/ThreadAIXCore.h
diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
index 1a98bb9334043..7e44ffbb1c051 100644
--- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
@@ -228,6 +228,65 @@ void DynamicLoaderAIXDYLD::ResolveExecutableModule(
target.SetExecutableModule(module_sp, eLoadDependentsNo);
}
+bool DynamicLoaderAIXDYLD::IsCoreFile() const {
+ return !m_process->IsLiveDebugSession();
+}
+
+void DynamicLoaderAIXDYLD::FillCoreLoaderData(lldb_private::DataExtractor &data,
+ uint64_t loader_offset, uint64_t loader_size ) {
+
+ static char *buffer = (char *)malloc(loader_size);
+ struct ld_info ldinfo[64];
+ char *buffer_complete;
+ struct ld_info *ptr;
+ int i = 0;
+
+ Log *log = GetLog(LLDBLog::DynamicLoader);
+ LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__);
+ ByteOrder byteorder = data.GetByteOrder();
+ data.ExtractBytes(loader_offset, loader_size, eByteOrderBig, buffer);
+ buffer_complete = buffer + loader_size;
+ ldinfo[0].ldinfo_next = 1;
+
+ while (ldinfo[i++].ldinfo_next != 0) {
+
+ ptr = (struct ld_info *)buffer;
+ ldinfo[i].ldinfo_next = ptr->ldinfo_next;
+ ldinfo[i].ldinfo_flags = ptr->ldinfo_flags;
+ ldinfo[i].ldinfo_core = ptr->ldinfo_core;
+ ldinfo[i].ldinfo_textorg = ptr->ldinfo_textorg;
+ ldinfo[i].ldinfo_textsize = ptr->ldinfo_textsize;
+ ldinfo[i].ldinfo_dataorg = ptr->ldinfo_dataorg;
+ ldinfo[i].ldinfo_datasize = ptr->ldinfo_datasize;
+
+ char *filename = &ptr->ldinfo_filename[0];
+ char *membername = filename + (strlen(filename) + 1);
+ strcpy(ldinfo[i].ldinfo_filename, filename);
+
+ buffer += ptr->ldinfo_next;
+ struct ld_info *ptr2 = &(ldinfo[i]);
+ char *pathName = ptr2->ldinfo_filename;
+ char pathWithMember[PATH_MAX] = {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());
+ LLDB_LOGF(log, "Module :%s", pathWithMember);
+ if (ModuleSP module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, true /* notify */)) {
+ UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr2->ldinfo_textorg, false, 1);
+ UpdateLoadedSectionsByType(module_sp, LLDB_INVALID_ADDRESS, (lldb::addr_t)ptr2->ldinfo_dataorg, false, 2);
+ // FIXME: .tdata, .bss
+ }
+ if (ptr2->ldinfo_next == 0) {
+ ptr2 = nullptr;
+ }
+ }
+}
+
void DynamicLoaderAIXDYLD::DidAttach() {
Log *log = GetLog(LLDBLog::DynamicLoader);
LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__);
@@ -361,7 +420,8 @@ void DynamicLoaderAIXDYLD::DidLaunch() {
#endif
}
-Status DynamicLoaderAIXDYLD::CanLoadImage() { return Status(); }
+Status DynamicLoaderAIXDYLD::CanLoadImage() {
+ return Status(); }
ThreadPlanSP
DynamicLoaderAIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h
index 0ffbe688e0069..097f8d048b77f 100644
--- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h
+++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h
@@ -33,6 +33,9 @@ class DynamicLoaderAIXDYLD : public DynamicLoader {
lldb::addr_t module_addr);
void OnUnloadModule(lldb::addr_t module_addr);
+ void FillCoreLoaderData(lldb_private::DataExtractor &data,
+ uint64_t loader_offset, uint64_t loader_size);
+
void DidAttach() override;
void DidLaunch() override;
Status CanLoadImage() override;
@@ -49,6 +52,9 @@ class DynamicLoaderAIXDYLD : public DynamicLoader {
/// Loads Module from inferior process.
void ResolveExecutableModule(lldb::ModuleSP &module_sp);
+ /// Returns true if the process is for a core file.
+ bool IsCoreFile() const;
+
private:
std::map<lldb::ModuleSP, lldb::addr_t> m_loaded_modules;
};
diff --git a/lldb/source/Plugins/ObjectFile/AIXCore/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/AIXCore/CMakeLists.txt
new file mode 100644
index 0000000000000..5656b33a61726
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/AIXCore/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_lldb_library(lldbPluginObjectFileAIXCore PLUGIN
+ ObjectFileAIXCore.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbTarget
+ lldbUtility
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp b/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp
new file mode 100644
index 0000000000000..5158fa4e25077
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp
@@ -0,0 +1,254 @@
+//===-- ObjectFileAIXCore.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 "ObjectFileAIXCore.h"
+
+#include <algorithm>
+#include <cassert>
+#include <unordered_map>
+#include <string.h>
+
+#include "lldb/Utility/FileSpecList.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Symbol/SymbolContext.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/Stream.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(ObjectFileAIXCore)
+
+enum CoreVersion : uint64_t {AIXCORE32 = 0xFEEDDB1, AIXCORE64 = 0xFEEDDB2};
+
+bool m_is_core = false;
+
+// Static methods.
+void ObjectFileAIXCore::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications);
+}
+
+void ObjectFileAIXCore::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ObjectFile *ObjectFileAIXCore::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(m_is_core)
+ {
+
+ bool mapped_writable = false;
+ if (!data_sp) {
+ data_sp = MapFileDataWritable(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ mapped_writable = true;
+ }
+
+ assert(data_sp);
+
+ const uint8_t *magic = data_sp->GetBytes() + data_offset;
+
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length) {
+ data_sp = MapFileDataWritable(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ mapped_writable = true;
+ magic = data_sp->GetBytes();
+ }
+
+ // If we didn't map the data as writable take ownership of the buffer.
+ if (!mapped_writable) {
+ data_sp = std::make_shared<DataBufferHeap>(data_sp->GetBytes(),
+ data_sp->GetByteSize());
+ data_offset = 0;
+ magic = data_sp->GetBytes();
+ }
+
+ std::unique_ptr<ObjectFileAIXCore> objfile_up(new ObjectFileAIXCore(
+ module_sp, data_sp, data_offset, file, file_offset, length));
+ ArchSpec spec = objfile_up->GetArchitecture();
+ objfile_up->SetModulesArchitecture(spec);
+ return objfile_up.release();
+
+ }
+}
+
+ObjectFile *ObjectFileAIXCore::CreateMemoryInstance(
+ const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) {
+ return nullptr;
+}
+
+size_t ObjectFileAIXCore::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 (ObjectFileAIXCore::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) {
+ // Need new ArchType???
+ 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 AIXCoreHeaderCheckFromMagic(uint32_t magic) {
+
+ Log *log = GetLog(LLDBLog::Modules);
+ switch (magic) {
+ case AIXCORE32:
+ LLDB_LOGF(log, "ObjectFileAIXCore: 32-bit not supported");
+ break;
+ case AIXCORE64:
+ m_is_core = true;
+ return 1;
+ break;
+ }
+ return 0;
+}
+
+bool ObjectFileAIXCore::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;
+ offset += 4; // Skipping to the coredump version
+ uint32_t magic = data.GetU32(&offset);
+ return AIXCoreHeaderCheckFromMagic(magic) != 0;
+}
+
+bool ObjectFileAIXCore::ParseHeader() {
+
+ return false;
+}
+
+ByteOrder ObjectFileAIXCore::GetByteOrder() const {
+ return eByteOrderBig;
+}
+
+bool ObjectFileAIXCore::IsExecutable() const {
+ return false;
+}
+
+uint32_t ObjectFileAIXCore::GetAddressByteSize() const {
+ return 8;
+}
+
+AddressClass ObjectFileAIXCore::GetAddressClass(addr_t file_addr) {
+ return AddressClass::eUnknown;
+}
+
+lldb::SymbolType ObjectFileAIXCore::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 ObjectFileAIXCore::ParseSymtab(Symtab &lldb_symtab) {
+}
+
+bool ObjectFileAIXCore::IsStripped() {
+ return false;
+}
+
+void ObjectFileAIXCore::CreateSections(SectionList &unified_section_list) {
+}
+
+void ObjectFileAIXCore::Dump(Stream *s) {
+}
+
+ArchSpec ObjectFileAIXCore::GetArchitecture() {
+ ArchSpec arch_spec = ArchSpec(eArchTypeXCOFF, XCOFF::TCPU_PPC64, LLDB_INVALID_CPUTYPE);
+ return arch_spec;
+}
+
+UUID ObjectFileAIXCore::GetUUID() {
+ return UUID();
+}
+
+uint32_t ObjectFileAIXCore::GetDependentModules(FileSpecList &files) {
+
+ auto original_size = files.GetSize();
+ return files.GetSize() - original_size;
+}
+
+Address ObjectFileAIXCore::GetImageInfoAddress(Target *target) {
+ return Address();
+}
+
+lldb_private::Address ObjectFileAIXCore::GetBaseAddress() {
+ return lldb_private::Address();
+}
+ObjectFile::Type ObjectFileAIXCore::CalculateType() {
+ return eTypeCoreFile;
+}
+
+ObjectFile::Strata ObjectFileAIXCore::CalculateStrata() {
+ return eStrataUnknown;
+}
+
+std::vector<ObjectFile::LoadableData>
+ObjectFileAIXCore::GetLoadableData(Target &target) {
+ std::vector<LoadableData> loadables;
+ return loadables;
+}
+
+lldb::WritableDataBufferSP
+ObjectFileAIXCore::MapFileDataWritable(const FileSpec &file, uint64_t Size,
+ uint64_t Offset) {
+ return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size,
+ Offset);
+}
+
+ObjectFileAIXCore::ObjectFileAIXCore(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)
+ {
+ if (file)
+ m_file = *file;
+}
+
+ObjectFileAIXCore::ObjectFileAIXCore(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)
+ {
+}
diff --git a/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.h b/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.h
new file mode 100644
index 0000000000000..5dbd78d919bb6
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.h
@@ -0,0 +1,121 @@
+//===-- ObjectFileAIXCore.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_AIXCORE_OBJECTFILEAIXCORE_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_AIXCORE_OBJECTFILEAIXCORE_H
+
+#include <cstdint>
+
+#include <vector>
+
+#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 ObjectFileAIXCore
+/// Generic AIX CORE object file reader.
+///
+/// This class provides a generic AIX Core (32/64 bit) reader plugin implementing
+/// the ObjectFile protocol.
+class ObjectFileAIXCore : public lldb_private::ObjectFile {
+public:
+ // Static Functions
+ static void Initialize();
+
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() { return "aix-core-obj"; }
+
+ static llvm::StringRef GetPluginDescriptionStatic() {
+ return "AIX core 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(); }
+
+ // ObjectFile Protocol.
+ bool ParseHeader() 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;
+
+ uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;
+
+ lldb_private::Address
+ GetImageInfoAddress(lldb_private::Target *target) override;
+ lldb_private::Address GetBaseAddress() override;
+
+ ObjectFile::Type CalculateType() override;
+
+ ObjectFile::Strata CalculateStrata() override;
+
+ ObjectFileAIXCore(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);
+
+ ObjectFileAIXCore(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP header_data_sp,
+ const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
+
+protected:
+
+ static bool ParseAIXCoreHeader(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset_ptr
+ );
+
+ std::vector<LoadableData>
+ GetLoadableData(lldb_private::Target &target) override;
+
+ static lldb::WritableDataBufferSP
+ MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,
+ uint64_t Offset);
+
+};
+
+#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_AIXCORE_OBJECTFILEAIXCORE_H
diff --git a/lldb/source/Plugins/ObjectFile/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/CMakeLists.txt
index 7abd0c96f4fd7..1605356fdb7f1 100644
--- a/lldb/source/Plugins/ObjectFile/CMakeLists.txt
+++ b/lldb/source/Plugins/ObjectFile/CMakeLists.txt
@@ -9,3 +9,4 @@ add_subdirectory(PECOFF)
add_subdirectory(XCOFF)
add_subdirectory(Placeholder)
add_subdirectory(wasm)
+add_subdirectory(AIXCore)
diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt
index 058b4b9ad2157..0b66ea18c82ce 100644
--- a/lldb/source/Plugins/Process/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/CMakeLists.txt
@@ -24,3 +24,4 @@ add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(FreeBSDKernel)
+add_subdirectory(aix-core)
diff --git a/lldb/source/Plugins/Process/aix-core/AIXCore.cpp b/lldb/source/Plugins/Process/aix-core/AIXCore.cpp
new file mode 100644
index 0000000000000..95e47b4d8be53
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/AIXCore.cpp
@@ -0,0 +1,116 @@
+//===-- AIXCore.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 <cstring>
+
+#include "lldb/Core/Section.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
+
+#include "AIXCore.h"
+
+using namespace AIXCORE;
+using namespace lldb;
+using namespace lldb_private;
+
+AIXCore64Header::AIXCore64Header() { memset(this, 0, sizeof(AIXCore64Header)); }
+
+
+bool AIXCore64Header::ParseRegisterContext(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ // The data is arranged in this order in this coredump file
+ // so we have to fetch in this exact order. But need to change
+ // the context structure order according to Infos_ppc64
+ for(int i = 0; i < 32; i++)
+ Fault.context.gpr[i] = data.GetU64(offset);
+ Fault.context.msr = data.GetU64(offset);
+ Fault.context.pc = data.GetU64(offset);
+ Fault.context.lr = data.GetU64(offset);
+ Fault.context.ctr = data.GetU64(offset);
+ Fault.context.cr = data.GetU32(offset);
+ Fault.context.xer = data.GetU32(offset);
+ Fault.context.fpscr = data.GetU32(offset);
+ Fault.context.fpscrx = data.GetU32(offset);
+ Fault.context.except[0] = data.GetU64(offset);
+ for(int i = 0; i < 32; i++)
+ Fault.context.fpr[i] = data.GetU64(offset);
+ Fault.context.fpeu = data.GetU8(offset);
+ Fault.context.fpinfo = data.GetU8(offset);
+ Fault.context.fpscr24_31 = data.GetU8(offset);
+ Fault.context.pad[0] = data.GetU8(offset);
+ Fault.context.excp_type = data.GetU32(offset);
+
+ return true;
+}
+bool AIXCore64Header::ParseThreadContext(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+
+ lldb::offset_t offset_to_regctx = *offset;
+ offset_to_regctx += sizeof(thrdentry64);
+ Fault.thread.ti_tid = data.GetU64(offset);
+ Fault.thread.ti_pid = data.GetU32(offset);
+ int ret = ParseRegisterContext(data, &offset_to_regctx);
+ return true;
+}
+
+bool AIXCore64Header::ParseUserData(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+ User.process.pi_pid = data.GetU32(offset);
+ User.process.pi_ppid = data.GetU32(offset);
+ User.process.pi_sid = data.GetU32(offset);
+ User.process.pi_pgrp = data.GetU32(offset);
+ User.process.pi_uid = data.GetU32(offset);
+ User.process.pi_suid = data.GetU32(offset);
+
+ *offset += 76;
+
+ ByteOrder byteorder = data.GetByteOrder();
+ size_t size = 33;
+ data.ExtractBytes(*offset, size, byteorder, User.process.pi_comm);
+ offset += size;
+
+ return true;
+}
+
+bool AIXCore64Header::ParseCoreHeader(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset) {
+
+ SignalNum = data.GetU8(offset);
+ Flag = data.GetU8(offset);
+ Entries = data.GetU16(offset);
+ Version = data.GetU32(offset);
+ FDInfo = data.GetU64(offset);
+
+ LoaderOffset = data.GetU64(offset);
+ LoaderSize = data.GetU64(offset);
+ NumberOfThreads = data.GetU32(offset);
+ Reserved0 = data.GetU32(offset);
+ ThreadContextOffset = data.GetU64(offset);
+ NumSegRegion = data.GetU64(offset);
+ SegRegionOffset = data.GetU64(offset);
+ StackOffset = data.GetU64(offset);
+ StackBaseAddr = data.GetU64(offset);
+ StackSize = data.GetU64(offset);
+ DataRegionOffset = data.GetU64(offset);
+ DataBaseAddr = data.GetU64(offset);
+ DataSize = data.GetU64(offset);
+
+ *offset += 104;
+ lldb::offset_t offset_to_user = (*offset + sizeof(ThreadContext64));
+ int ret = 0;
+ ret = ParseThreadContext(data, offset);
+ ret = ParseUserData(data, &offset_to_user);
+
+ return true;
+
+}
+
diff --git a/lldb/source/Plugins/Process/aix-core/AIXCore.h b/lldb/source/Plugins/Process/aix-core/AIXCore.h
new file mode 100644
index 0000000000000..3d78d5e92c7ab
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/AIXCore.h
@@ -0,0 +1,125 @@
+//===-- AIXCore.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
+//
+// Notes about AIX Process core dumps:
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_AIXCORE_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_AIXCORE_H
+
+#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+#include <cstring>
+#include <type_traits>
+
+#include <sys/types.h>
+#include <procinfo.h>
+
+namespace AIXCORE {
+
+struct RegContext {
+ // The data is arranged in order as filled by AIXCore.cpp in this coredump file
+ // so we have to fetch in that exact order, refer there.
+ // But need to change
+ // the context structure in order according to Infos_ppc64
+ uint64_t gpr[32]; /* 64-bit gprs */
+ unsigned long pc; /* msr */
+ unsigned long msr; /* iar */
+ unsigned long origr3; /* iar */
+ unsigned long ctr; /* CTR */
+ unsigned long lr; /* LR */
+ unsigned long xer; /* XER */
+ unsigned long cr; /* CR */
+ unsigned long softe; /* CR */
+ unsigned long trap; /* CR */
+ unsigned int fpscr; /* floating pt status reg */
+ unsigned int fpscrx; /* software ext to fpscr */
+ unsigned long except[1]; /* exception address */
+ double fpr[32]; /* floating pt regs */
+ char fpeu; /* floating pt ever used */
+ char fpinfo; /* floating pt info */
+ char fpscr24_31; /* bits 24-31 of 64-bit FPSCR */
+ char pad[1];
+ int excp_type; /* exception type */
+};
+
+ struct ThreadContext64 {
+ struct thrdentry64 thread;
+ struct RegContext context;
+ };
+
+ struct UserData {
+
+ struct procentry64 process;
+ unsigned long long reserved[16];
+ };
+
+ struct AIXCore64Header {
+
+ int8_t SignalNum; /* signal number (cause of error) */
+ int8_t Flag; /* flag to describe core dump type */
+ uint16_t Entries; /* number of core dump modules */
+ uint32_t Version; /* core file format number */
+ uint64_t FDInfo; /* offset to fd region in file */
+
+ uint64_t LoaderOffset; /* offset to loader region in file */
+ uint64_t LoaderSize; /* size of loader region */
+
+ uint32_t NumberOfThreads ; /* number of elements in thread table */
+ uint32_t Reserved0; /* Padding */
+ uint64_t ThreadContextOffset; /* offset to thread context table */
+
+ uint64_t NumSegRegion; /* n of elements in segregion */
+ uint64_t SegRegionOffset; /* offset to start of segregion table */
+
+ uint64_t StackOffset; /* offset of user stack in file */
+ uint64_t StackBaseAddr; /* base address of user stack region */
+ uint64_t StackSize; /* size of user stack region */
+
+ uint64_t DataRegionOffset; /* offset to user data region */
+ uint64_t DataBaseAddr; /* base address of user data region */
+ uint64_t DataSize; /* size of user data region */
+ uint64_t SDataBase; /* base address of sdata region */
+ uint64_t SDataSize; /* size of sdata region */
+
+ uint64_t NumVMRegions; /* number of anonymously mapped areas */
+ uint64_t VMOffset; /* offset to start of vm_infox table */
+
+ int32_t ProcessorImplementation; /* processor implementation */
+ uint32_t NumElementsCTX; /* n of elements in extended ctx table*/
+ uint64_t CPRSOffset; /* Checkpoint/Restart offset */
+ uint64_t ExtendedContextOffset; /* extended context offset */
+ uint64_t OffsetUserKey; /* Offset to user-key exception data */
+ uint64_t OffsetLoaderTLS; /* offset to the loader region in file
+ when a process uses TLS data */
+ uint64_t TLSLoaderSize; /* size of the above loader region */
+ uint64_t ExtendedProcEntry; /* Extended procentry64 information */
+ uint64_t Reserved[2];
+
+ struct ThreadContext64 Fault;
+
+ struct UserData User;
+
+ AIXCore64Header();
+
+ bool ParseCoreHeader(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset);
+ bool ParseThreadContext(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset);
+ bool ParseUserData(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset);
+ bool ParseRegisterContext(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset);
+ bool ParseLoaderData(lldb_private::DataExtractor &data,
+ lldb::offset_t *offset);
+
+ };
+
+
+}
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_AIXCORE_H
diff --git a/lldb/source/Plugins/Process/aix-core/CMakeLists.txt b/lldb/source/Plugins/Process/aix-core/CMakeLists.txt
new file mode 100644
index 0000000000000..347717a362491
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_definitions("-D_ALL_SOURCE")
+
+add_lldb_library(lldbPluginProcessAIXCore PLUGIN
+ ProcessAIXCore.cpp
+ AIXCore.cpp
+ ThreadAIXCore.cpp
+ RegisterContextCoreAIX_ppc64.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ BinaryFormat
+ Support
+ )
diff --git a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
new file mode 100644
index 0000000000000..9300aa14ac4db
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
@@ -0,0 +1,251 @@
+//===-- ProcessAIXCore.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 <cstdlib>
+
+#include <memory>
+#include <mutex>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
+
+#include "llvm/Support/Threading.h"
+#include "Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.h"
+
+#include "ProcessAIXCore.h"
+#include "AIXCore.h"
+#include "ThreadAIXCore.h"
+
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(ProcessAIXCore)
+
+llvm::StringRef ProcessAIXCore::GetPluginDescriptionStatic() {
+ return "AIX core dump plug-in.";
+}
+
+void ProcessAIXCore::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+ });
+}
+
+void ProcessAIXCore::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessAIXCore::CreateInstance);
+}
+
+lldb::ProcessSP ProcessAIXCore::CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file,
+ bool can_connect) {
+ lldb::ProcessSP process_sp;
+ if (crash_file && !can_connect) {
+ const size_t header_size = sizeof(AIXCORE::AIXCore64Header);
+
+ auto data_sp = FileSystem::Instance().CreateDataBuffer(
+ crash_file->GetPath(), header_size, 0);
+
+ if (data_sp && data_sp->GetByteSize() == header_size) {
+ AIXCORE::AIXCore64Header aixcore_header;
+ DataExtractor data(data_sp, lldb::eByteOrderBig, 4);
+ lldb::offset_t data_offset = 0;
+ if(aixcore_header.ParseCoreHeader(data, &data_offset)) {
+ process_sp = std::make_shared<ProcessAIXCore>(target_sp, listener_sp,
+ *crash_file);
+ }
+ }
+
+ }
+ return process_sp;
+}
+
+// ProcessAIXCore constructor
+ProcessAIXCore::ProcessAIXCore(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec &core_file)
+ : PostMortemProcess(target_sp, listener_sp, core_file) {}
+
+// Destructor
+ProcessAIXCore::~ProcessAIXCore() {
+ Clear();
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
+ Finalize(true /* destructing */);
+}
+
+bool ProcessAIXCore::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+
+ if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
+ ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
+ Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
+ nullptr, nullptr, nullptr));
+ if (m_core_module_sp) {
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile){
+ return true;
+ }
+ }
+ }
+ return false;
+
+}
+
+ArchSpec ProcessAIXCore::GetArchitecture() {
+
+ ArchSpec arch = m_core_module_sp->GetObjectFile()->GetArchitecture();
+
+ ArchSpec target_arch = GetTarget().GetArchitecture();
+ arch.MergeFrom(target_arch);
+
+ return arch;
+}
+
+lldb_private::DynamicLoader *ProcessAIXCore::GetDynamicLoader() {
+ if (m_dyld_up.get() == nullptr) {
+ m_dyld_up.reset(DynamicLoader::FindPlugin(
+ this, DynamicLoaderAIXDYLD::GetPluginNameStatic()));
+ }
+ return m_dyld_up.get();
+}
+
+void ProcessAIXCore::ParseAIXCoreFile() {
+
+ Log *log = GetLog(LLDBLog::Process);
+ AIXSigInfo siginfo;
+ ThreadData thread_data;
+
+ const lldb_private::UnixSignals &unix_signals = *GetUnixSignals();
+ const ArchSpec &arch = GetArchitecture();
+
+ siginfo.Parse(m_aixcore_header, arch, unix_signals);
+ thread_data.siginfo = siginfo;
+ SetID(m_aixcore_header.User.process.pi_pid);
+
+ thread_data.name.assign (m_aixcore_header.User.process.pi_comm,
+ strnlen (m_aixcore_header.User.process.pi_comm,
+ sizeof (m_aixcore_header.User.process.pi_comm)));
+
+ lldb::DataBufferSP data_buffer_sp(new lldb_private::DataBufferHeap(sizeof(m_aixcore_header.Fault.context), 0));
+
+ memcpy(static_cast<void *>(const_cast<uint8_t *>(data_buffer_sp->GetBytes())),
+ &m_aixcore_header.Fault.context, sizeof(m_aixcore_header.Fault.context));
+
+ lldb_private::DataExtractor data(data_buffer_sp, lldb::eByteOrderBig, 8);
+
+ thread_data.gpregset = DataExtractor(data, 0, sizeof(m_aixcore_header.Fault.context));
+ m_thread_data.push_back(thread_data);
+ LLDB_LOGF(log, "ProcessAIXCore: Parsing Complete!");
+
+}
+
+// Process Control
+Status ProcessAIXCore::DoLoadCore() {
+
+ Status error;
+ if (!m_core_module_sp) {
+ error = Status::FromErrorString("invalid core module");
+ return error;
+ }
+
+ FileSpec file = m_core_module_sp->GetObjectFile()->GetFileSpec();
+
+ if (file) {
+ const size_t header_size = sizeof(AIXCORE::AIXCore64Header);
+ auto data_sp = FileSystem::Instance().CreateDataBuffer(
+ file.GetPath(), -1, 0);
+ if (data_sp && data_sp->GetByteSize() != 0) {
+
+ DataExtractor data(data_sp, lldb::eByteOrderBig, 4);
+ lldb::offset_t data_offset = 0;
+ m_aixcore_header.ParseCoreHeader(data, &data_offset);
+ auto dyld = static_cast<DynamicLoaderAIXDYLD *>(GetDynamicLoader());
+ dyld->FillCoreLoaderData(data, m_aixcore_header.LoaderOffset,
+ m_aixcore_header.LoaderSize);
+
+ } else {
+ error = Status::FromErrorString("invalid data");
+ return error;
+ }
+ } else {
+ error = Status::FromErrorString("invalid file");
+ return error;
+ }
+
+ m_thread_data_valid = true;
+ ParseAIXCoreFile();
+ ArchSpec arch(m_core_module_sp->GetArchitecture());
+
+ ArchSpec target_arch = GetTarget().GetArchitecture();
+ ArchSpec core_arch(m_core_module_sp->GetArchitecture());
+ target_arch.MergeFrom(core_arch);
+ GetTarget().SetArchitecture(target_arch);
+
+ lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
+ if (!exe_module_sp) {
+ ModuleSpec exe_module_spec;
+ exe_module_spec.GetArchitecture() = arch;
+ exe_module_spec.GetFileSpec().SetFile(m_aixcore_header.User.process.pi_comm,
+ FileSpec::Style::native);
+ exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, true);
+ GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
+ }
+
+ return error;
+}
+
+bool ProcessAIXCore::DoUpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list)
+{
+ const ThreadData &td = m_thread_data[0];
+
+ lldb::ThreadSP thread_sp =
+ std::make_shared<ThreadAIXCore>(*this, td);
+ new_thread_list.AddThread(thread_sp);
+
+ return true;
+}
+
+void ProcessAIXCore::RefreshStateAfterStop() {}
+
+// Process Memory
+size_t ProcessAIXCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) {
+ if (lldb::ABISP abi_sp = GetABI())
+ addr = abi_sp->FixAnyAddress(addr);
+
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // in core files we have it all cached our our core file anyway.
+ return DoReadMemory(addr, buf, size, error);
+}
+
+size_t ProcessAIXCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Status &error) { return 0; }
+
+Status ProcessAIXCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo ®ion_info) {
+ return Status();
+}
+
+Status ProcessAIXCore::DoDestroy() { return Status(); }
diff --git a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h
new file mode 100644
index 0000000000000..9880c491689ca
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h
@@ -0,0 +1,100 @@
+//===-- ProcessAIXCore.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
+//
+// Notes about AIX Process core dumps:
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_PROCESSAIXCORE_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_PROCESSAIXCORE_H
+
+#include <list>
+#include <vector>
+
+#include "lldb/Target/PostMortemProcess.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Target/Process.h"
+#include "AIXCore.h"
+#include "ThreadAIXCore.h"
+
+struct ThreadData;
+
+class ProcessAIXCore : public lldb_private::PostMortemProcess {
+public:
+ // Constructors and Destructors
+ static lldb::ProcessSP
+ CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const lldb_private::FileSpec *crash_file_path,
+ bool can_connect);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() { return "aix-core"; }
+
+ static llvm::StringRef GetPluginDescriptionStatic();
+
+ // Constructors and Destructors
+ ProcessAIXCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
+ const lldb_private::FileSpec &core_file);
+
+ ~ProcessAIXCore() override;
+
+ // PluginInterface protocol
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+ // Process Control
+ lldb_private::Status DoDestroy() override;
+
+ lldb_private::Status WillResume() override {
+ return lldb_private::Status::FromErrorStringWithFormatv(
+ "error: {0} does not support resuming processes", GetPluginName());
+ }
+
+ bool WarnBeforeDetach() const override { return false; }
+
+ lldb_private::ArchSpec GetArchitecture();
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ // Creating a new process, or attaching to an existing one
+ lldb_private::Status DoLoadCore() override;
+
+ bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+
+ lldb_private::Status
+ DoGetMemoryRegionInfo(lldb::addr_t load_addr,
+ lldb_private::MemoryRegionInfo ®ion_info) override;
+
+ void RefreshStateAfterStop() override;
+
+ lldb_private::DynamicLoader *GetDynamicLoader() override;
+
+ // Process Memory
+ size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Status &error) override;
+
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ lldb_private::Status &error) override;
+
+ void ParseAIXCoreFile();
+
+
+private:
+ lldb::ModuleSP m_core_module_sp;
+ std::string m_dyld_plugin_name;
+
+ // True if m_thread_contexts contains valid entries
+ bool m_thread_data_valid = false;
+ AIXCORE::AIXCore64Header m_aixcore_header;
+
+ std::vector<ThreadData> m_thread_data;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_PROCESSAIXCORE_H
diff --git a/lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.cpp b/lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.cpp
new file mode 100644
index 0000000000000..b243017bf9a2a
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.cpp
@@ -0,0 +1,136 @@
+//===-- RegisterContextCoreAIX_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
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextCoreAIX_ppc64.h"
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
+#include "Plugins/Process/elf-core/RegisterUtilities.h"
+
+#include <memory>
+
+using namespace lldb_private;
+
+RegisterContextCoreAIX_ppc64::RegisterContextCoreAIX_ppc64(
+ Thread &thread, RegisterInfoInterface *register_info,
+ const DataExtractor &gpregset)
+ : RegisterContextPOSIX_ppc64le(thread, 0, register_info) {
+ m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
+ gpregset.GetByteSize());
+ m_gpr.SetData(m_gpr_buffer);
+ m_gpr.SetByteOrder(gpregset.GetByteOrder());
+
+ // This Code is for Registers like FPR, VSR, VMX and is disabled right now.
+ // It will be implemented as per need.
+
+ /* ArchSpec arch = register_info->GetTargetArchitecture();
+ DataExtractor fpregset;// = getRegset(notes, arch.GetTriple(), FPR_Desc);
+ m_fpr_buffer = std::make_shared<DataBufferHeap>(fpregset.GetDataStart(),
+ fpregset.GetByteSize());
+ m_fpr.SetData(m_fpr_buffer);
+ m_fpr.SetByteOrder(fpregset.GetByteOrder());
+
+ DataExtractor vmxregset;// = getRegset(notes, arch.GetTriple(), PPC_VMX_Desc);
+ m_vmx_buffer = std::make_shared<DataBufferHeap>(vmxregset.GetDataStart(),
+ vmxregset.GetByteSize());
+ m_vmx.SetData(m_vmx_buffer);
+ m_vmx.SetByteOrder(vmxregset.GetByteOrder());
+
+ DataExtractor vsxregset;// = getRegset(notes, arch.GetTriple(), PPC_VSX_Desc);
+ m_vsx_buffer = std::make_shared<DataBufferHeap>(vsxregset.GetDataStart(),
+ vsxregset.GetByteSize());
+ m_vsx.SetData(m_vsx_buffer);
+ m_vsx.SetByteOrder(vsxregset.GetByteOrder());*/
+}
+
+size_t RegisterContextCoreAIX_ppc64::GetFPRSize() const {
+ return k_num_fpr_registers_ppc64le * sizeof(uint64_t);
+}
+
+size_t RegisterContextCoreAIX_ppc64::GetVMXSize() const {
+ return (k_num_vmx_registers_ppc64le - 1) * sizeof(uint64_t) * 2 +
+ sizeof(uint32_t);
+}
+
+size_t RegisterContextCoreAIX_ppc64::GetVSXSize() const {
+ return k_num_vsx_registers_ppc64le * sizeof(uint64_t) * 2;
+}
+
+bool RegisterContextCoreAIX_ppc64::ReadRegister(
+ const RegisterInfo *reg_info, RegisterValue &value) {
+ lldb::offset_t offset = reg_info->byte_offset;
+
+ if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
+ uint64_t v;
+ offset -= GetGPRSize();
+ offset = m_fpr.CopyData(offset, reg_info->byte_size, &v);
+
+ if (offset == reg_info->byte_size) {
+ value.SetBytes(&v, reg_info->byte_size, m_fpr.GetByteOrder());
+ return true;
+ }
+ } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) {
+ uint32_t v[4];
+ offset -= GetGPRSize() + GetFPRSize();
+ offset = m_vmx.CopyData(offset, reg_info->byte_size, &v);
+
+ if (offset == reg_info->byte_size) {
+ value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder());
+ return true;
+ }
+ } else if (IsVSX(reg_info->kinds[lldb::eRegisterKindLLDB])) {
+ uint32_t v[4];
+ lldb::offset_t tmp_offset;
+ offset -= GetGPRSize() + GetFPRSize() + GetVMXSize();
+
+ if (offset < GetVSXSize() / 2) {
+ tmp_offset = m_vsx.CopyData(offset / 2, reg_info->byte_size / 2, &v);
+
+ if (tmp_offset != reg_info->byte_size / 2) {
+ return false;
+ }
+
+ uint8_t *dst = (uint8_t *)&v + sizeof(uint64_t);
+ tmp_offset = m_fpr.CopyData(offset / 2, reg_info->byte_size / 2, dst);
+
+ if (tmp_offset != reg_info->byte_size / 2) {
+ return false;
+ }
+
+ value.SetBytes(&v, reg_info->byte_size, m_vsx.GetByteOrder());
+ return true;
+ } else {
+ offset =
+ m_vmx.CopyData(offset - GetVSXSize() / 2, reg_info->byte_size, &v);
+ if (offset == reg_info->byte_size) {
+ value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder());
+ return true;
+ }
+ }
+ } else {
+ uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+
+ if (offset == reg_info->byte_offset + reg_info->byte_size) {
+ if (reg_info->byte_size < sizeof(v))
+ value = (uint32_t)v;
+ else
+ value = v;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool RegisterContextCoreAIX_ppc64::WriteRegister(
+ const RegisterInfo *reg_info, const RegisterValue &value) {
+ return false;
+}
diff --git a/lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.h b/lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.h
new file mode 100644
index 0000000000000..8f1f71ce8d884
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/RegisterContextCoreAIX_ppc64.h
@@ -0,0 +1,46 @@
+//===-- RegisterContextCoreAIX_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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_REGISTERCONTEXTAIXCORE_PPC64_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_REGISTERCONTEXTAIXCORE_PPC64_H
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h"
+#include "lldb/Utility/DataExtractor.h"
+
+class RegisterContextCoreAIX_ppc64 : public RegisterContextPOSIX_ppc64le {
+public:
+ RegisterContextCoreAIX_ppc64(
+ lldb_private::Thread &thread,
+ lldb_private::RegisterInfoInterface *register_info,
+ const lldb_private::DataExtractor &gpregset);
+
+ bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
+
+ bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
+
+protected:
+ size_t GetFPRSize() const;
+
+ size_t GetVMXSize() const;
+
+ size_t GetVSXSize() const;
+
+private:
+ lldb::DataBufferSP m_gpr_buffer;
+ lldb::DataBufferSP m_fpr_buffer;
+ lldb::DataBufferSP m_vmx_buffer;
+ lldb::DataBufferSP m_vsx_buffer;
+ lldb_private::DataExtractor m_gpr;
+ lldb_private::DataExtractor m_fpr;
+ lldb_private::DataExtractor m_vmx;
+ lldb_private::DataExtractor m_vsx;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_REGISTERCONTEXTAIXCORE_PPC64_H
diff --git a/lldb/source/Plugins/Process/aix-core/ThreadAIXCore.cpp b/lldb/source/Plugins/Process/aix-core/ThreadAIXCore.cpp
new file mode 100644
index 0000000000000..979e5199fe24d
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/ThreadAIXCore.cpp
@@ -0,0 +1,127 @@
+//===-- ThreadAIXCore.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/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/UnixSignals.h"
+#include "lldb/Target/Unwind.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/ProcessInfo.h"
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h"
+#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
+#include "Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h"
+#include "RegisterContextCoreAIX_ppc64.h"
+
+#include "ProcessAIXCore.h"
+#include "AIXCore.h"
+#include "ThreadAIXCore.h"
+
+#include <memory>
+#include <iostream>
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Construct a Thread object with given data
+ThreadAIXCore::ThreadAIXCore(Process &process, const ThreadData &td)
+ : Thread(process, td.tid), m_thread_name(td.name), m_thread_reg_ctx_sp(),
+ m_gpregset_data(td.gpregset),
+ m_siginfo(std::move(td.siginfo)) {}
+
+ThreadAIXCore::~ThreadAIXCore() { DestroyThread(); }
+
+void ThreadAIXCore::RefreshStateAfterStop() {
+ GetRegisterContext()->InvalidateIfNeeded(false);
+}
+
+RegisterContextSP ThreadAIXCore::GetRegisterContext() {
+ if (!m_reg_context_sp) {
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
+ }
+ return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadAIXCore::CreateRegisterContextForFrame(StackFrame *frame) {
+ RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ bool is_linux = false;
+ if (concrete_frame_idx == 0) {
+ if (m_thread_reg_ctx_sp)
+ return m_thread_reg_ctx_sp;
+
+ ProcessAIXCore *process = static_cast<ProcessAIXCore *>(GetProcess().get());
+ ArchSpec arch = process->GetArchitecture();
+ RegisterInfoInterface *reg_interface = nullptr;
+
+ switch (arch.GetMachine()) {
+ case llvm::Triple::ppc64:
+ reg_interface = new RegisterInfoPOSIX_ppc64le(arch);
+ m_thread_reg_ctx_sp = std::make_shared<RegisterContextCoreAIX_ppc64>(
+ *this, reg_interface, m_gpregset_data);
+ break;
+ default:
+ break;
+ }
+ reg_ctx_sp = m_thread_reg_ctx_sp;
+ } else {
+ reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
+ }
+ return reg_ctx_sp;
+}
+
+bool ThreadAIXCore::CalculateStopInfo() {
+ ProcessSP process_sp(GetProcess());
+ if (!process_sp)
+ return false;
+
+ lldb::UnixSignalsSP unix_signals_sp(process_sp->GetUnixSignals());
+ if (!unix_signals_sp)
+ return false;
+
+ const char *sig_description;
+ std::string description = m_siginfo.GetDescription(*unix_signals_sp);
+ if (description.empty())
+ sig_description = nullptr;
+ else
+ sig_description = description.c_str();
+
+ SetStopInfo(StopInfo::CreateStopReasonWithSignal(
+ *this, m_siginfo.si_signo, sig_description, m_siginfo.si_code));
+
+ SetStopInfo(m_stop_info_sp);
+ return true;
+}
+
+void AIXSigInfo::Parse(const AIXCORE::AIXCore64Header data, const ArchSpec &arch,
+ const lldb_private::UnixSignals &unix_signals) {
+ si_signo = data.SignalNum;
+ sigfault.si_addr = data.Fault.context.pc;
+}
+
+AIXSigInfo::AIXSigInfo() { memset(this, 0, sizeof(AIXSigInfo)); }
+
+size_t AIXSigInfo::GetSize(const lldb_private::ArchSpec &arch) {
+ return sizeof(AIXSigInfo);
+}
+
+std::string AIXSigInfo::GetDescription(
+ const lldb_private::UnixSignals &unix_signals) const {
+ return unix_signals.GetSignalDescription(si_signo, 0,
+ sigfault.si_addr);
+
+}
diff --git a/lldb/source/Plugins/Process/aix-core/ThreadAIXCore.h b/lldb/source/Plugins/Process/aix-core/ThreadAIXCore.h
new file mode 100644
index 0000000000000..9ee157e9b2b9b
--- /dev/null
+++ b/lldb/source/Plugins/Process/aix-core/ThreadAIXCore.h
@@ -0,0 +1,110 @@
+//===-- ThreadAIXCore.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_PROCESS_AIX_CORE_THREADAIXCORE_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_THREADAIXCORE_H
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "llvm/ADT/DenseMap.h"
+#include <optional>
+#include <string>
+#include "ProcessAIXCore.h"
+#include "AIXCore.h"
+#include "ThreadAIXCore.h"
+
+namespace lldb_private {
+class ProcessInstanceInfo;
+}
+
+struct AIXSigInfo {
+
+ //COPY siginfo_t correctly for AIX version
+ int32_t si_signo; // Order matters for the first 3.
+ int32_t si_errno;
+ int32_t si_code;
+ struct alignas(8) {
+ lldb::addr_t si_addr;
+ int16_t si_addr_lsb;
+ union {
+ struct {
+ lldb::addr_t _lower;
+ lldb::addr_t _upper;
+ } _addr_bnd;
+ uint32_t _pkey;
+ } bounds;
+ } sigfault;
+
+ enum SigInfoNoteType : uint8_t { eUnspecified, eNT_SIGINFO };
+ SigInfoNoteType note_type;
+
+ AIXSigInfo();
+
+ void Parse(const AIXCORE::AIXCore64Header data,
+ const lldb_private::ArchSpec &arch,
+ const lldb_private::UnixSignals &unix_signals);
+
+ std::string
+ GetDescription(const lldb_private::UnixSignals &unix_signals) const;
+
+ static size_t GetSize(const lldb_private::ArchSpec &arch);
+};
+
+struct ThreadData {
+ lldb_private::DataExtractor gpregset;
+ std::vector<lldb_private::DataExtractor> notes;
+ lldb::tid_t tid;
+ std::string name;
+ AIXSigInfo siginfo;
+ int prstatus_sig = 0;
+};
+
+class ThreadAIXCore : public lldb_private::Thread {
+public:
+ ThreadAIXCore(lldb_private::Process &process, const ThreadData &td);
+
+ ~ThreadAIXCore() override;
+
+ void RefreshStateAfterStop() override;
+
+ lldb::RegisterContextSP GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+
+ static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
+
+ const char *GetName() override {
+ if (m_thread_name.empty())
+ return nullptr;
+ return m_thread_name.c_str();
+ }
+
+ void SetName(const char *name) override {
+ if (name && name[0])
+ m_thread_name.assign(name);
+ else
+ m_thread_name.clear();
+ }
+
+ void CreateStopFromSigInfo(const AIXSigInfo &siginfo,
+ const lldb_private::UnixSignals &unix_signals);
+
+protected:
+ // Member variables.
+ std::string m_thread_name;
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+ lldb_private::DataExtractor m_gpregset_data;
+ std::vector<lldb_private::DataExtractor> m_notes;
+ AIXSigInfo m_siginfo;
+
+ bool CalculateStopInfo() override;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_AIX_CORE_THREADAIXCORE_H
>From 57cb8058646103eeada1f92e039d9c54ccd4788f Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 17 Mar 2025 07:31:26 -0500
Subject: [PATCH 40/55] Merge branch 'llvm:main' into llvmgh-101657
---
lldb/cmake/modules/LLDBConfig.cmake | 4 ----
1 file changed, 4 deletions(-)
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index 312791ce36fc7..9df71edd8b359 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -292,11 +292,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.
-<<<<<<< HEAD
-if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows|AIX")
-=======
if (CMAKE_SYSTEM_NAME MATCHES "AIX|Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows")
->>>>>>> upstream/main
set(LLDB_CAN_USE_LLDB_SERVER ON)
else()
set(LLDB_CAN_USE_LLDB_SERVER OFF)
>From 0767ef036d3f82d1429e04a319feb6627ea08158 Mon Sep 17 00:00:00 2001
From: Dhruv Srivastava <dhruv.srivastava at ibm.com>
Date: Tue, 18 Mar 2025 15:03:17 +0530
Subject: [PATCH 41/55] Error Handling (#32)
* Error Handling for aix core module
---
.../AIX-DYLD/DynamicLoaderAIXDYLD.cpp | 12 +++++++-----
.../ObjectFile/AIXCore/ObjectFileAIXCore.cpp | 15 +++++++--------
lldb/source/Plugins/Process/aix-core/AIXCore.cpp | 2 +-
.../Plugins/Process/aix-core/ProcessAIXCore.cpp | 11 ++++++++---
4 files changed, 23 insertions(+), 17 deletions(-)
diff --git a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
index 7e44ffbb1c051..12f24c049f373 100644
--- a/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/AIX-DYLD/DynamicLoaderAIXDYLD.cpp
@@ -235,17 +235,19 @@ bool DynamicLoaderAIXDYLD::IsCoreFile() const {
void DynamicLoaderAIXDYLD::FillCoreLoaderData(lldb_private::DataExtractor &data,
uint64_t loader_offset, uint64_t loader_size ) {
+ Log *log = GetLog(LLDBLog::DynamicLoader);
+ LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__);
static char *buffer = (char *)malloc(loader_size);
- struct ld_info ldinfo[64];
- char *buffer_complete;
+ if (buffer == NULL) {
+ LLDB_LOG(log, "Buffer allocation failed error: {0}", std::strerror(errno));
+ return;
+ }
+ struct ld_info ldinfo[64] = {};
struct ld_info *ptr;
int i = 0;
- Log *log = GetLog(LLDBLog::DynamicLoader);
- LLDB_LOGF(log, "DynamicLoaderAIXDYLD::%s()", __FUNCTION__);
ByteOrder byteorder = data.GetByteOrder();
data.ExtractBytes(loader_offset, loader_size, eByteOrderBig, buffer);
- buffer_complete = buffer + loader_size;
ldinfo[0].ldinfo_next = 1;
while (ldinfo[i++].ldinfo_next != 0) {
diff --git a/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp b/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp
index 5158fa4e25077..0ba1056866937 100644
--- a/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp
+++ b/lldb/source/Plugins/ObjectFile/AIXCore/ObjectFileAIXCore.cpp
@@ -73,8 +73,6 @@ ObjectFile *ObjectFileAIXCore::CreateInstance(const lldb::ModuleSP &module_sp,
assert(data_sp);
- const uint8_t *magic = data_sp->GetBytes() + data_offset;
-
// Update the data to contain the entire file if it doesn't already
if (data_sp->GetByteSize() < length) {
data_sp = MapFileDataWritable(*file, length, file_offset);
@@ -82,7 +80,6 @@ ObjectFile *ObjectFileAIXCore::CreateInstance(const lldb::ModuleSP &module_sp,
return nullptr;
data_offset = 0;
mapped_writable = true;
- magic = data_sp->GetBytes();
}
// If we didn't map the data as writable take ownership of the buffer.
@@ -90,7 +87,6 @@ ObjectFile *ObjectFileAIXCore::CreateInstance(const lldb::ModuleSP &module_sp,
data_sp = std::make_shared<DataBufferHeap>(data_sp->GetBytes(),
data_sp->GetByteSize());
data_offset = 0;
- magic = data_sp->GetBytes();
}
std::unique_ptr<ObjectFileAIXCore> objfile_up(new ObjectFileAIXCore(
@@ -124,19 +120,22 @@ size_t ObjectFileAIXCore::GetModuleSpecifications(
return specs.GetSize() - initial_count;
}
-static uint32_t AIXCoreHeaderCheckFromMagic(uint32_t magic) {
+static bool AIXCoreHeaderCheckFromMagic(uint32_t magic) {
Log *log = GetLog(LLDBLog::Modules);
+ bool ret = false;
switch (magic) {
case AIXCORE32:
LLDB_LOGF(log, "ObjectFileAIXCore: 32-bit not supported");
break;
case AIXCORE64:
m_is_core = true;
- return 1;
+ ret = true;
+ break;
+ default:
break;
}
- return 0;
+ return ret;
}
bool ObjectFileAIXCore::MagicBytesMatch(DataBufferSP &data_sp,
@@ -147,7 +146,7 @@ bool ObjectFileAIXCore::MagicBytesMatch(DataBufferSP &data_sp,
lldb::offset_t offset = 0;
offset += 4; // Skipping to the coredump version
uint32_t magic = data.GetU32(&offset);
- return AIXCoreHeaderCheckFromMagic(magic) != 0;
+ return AIXCoreHeaderCheckFromMagic(magic);
}
bool ObjectFileAIXCore::ParseHeader() {
diff --git a/lldb/source/Plugins/Process/aix-core/AIXCore.cpp b/lldb/source/Plugins/Process/aix-core/AIXCore.cpp
index 95e47b4d8be53..bc496b5af273f 100644
--- a/lldb/source/Plugins/Process/aix-core/AIXCore.cpp
+++ b/lldb/source/Plugins/Process/aix-core/AIXCore.cpp
@@ -110,7 +110,7 @@ bool AIXCore64Header::ParseCoreHeader(lldb_private::DataExtractor &data,
ret = ParseThreadContext(data, offset);
ret = ParseUserData(data, &offset_to_user);
- return true;
+ return ret;
}
diff --git a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
index 9300aa14ac4db..cfcbe1a216116 100644
--- a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
+++ b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
@@ -208,8 +208,10 @@ Status ProcessAIXCore::DoLoadCore() {
exe_module_spec.GetArchitecture() = arch;
exe_module_spec.GetFileSpec().SetFile(m_aixcore_header.User.process.pi_comm,
FileSpec::Style::native);
- exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, true);
- GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
+ exe_module_sp =
+ GetTarget().GetOrCreateModule(exe_module_spec, true /* notify */);
+ if (exe_module_sp)
+ GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
}
return error;
@@ -232,8 +234,11 @@ void ProcessAIXCore::RefreshStateAfterStop() {}
// Process Memory
size_t ProcessAIXCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
+ if(addr == LLDB_INVALID_ADDRESS)
+ return 0;
+
if (lldb::ABISP abi_sp = GetABI())
- addr = abi_sp->FixAnyAddress(addr);
+ addr = abi_sp->FixAnyAddress(addr);
// Don't allow the caching that lldb_private::Process::ReadMemory does since
// in core files we have it all cached our our core file anyway.
>From 8214e5d8cc52b486d3c3f5f4615848b1782cfcf8 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Wed, 26 Mar 2025 01:34:36 -0500
Subject: [PATCH 42/55] Merge branch 'llvm:main' into gh-101657
---
lldb/source/Host/common/Host.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 575bb46216d19..6cf1112511c3f 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -20,7 +20,6 @@
#include <spawn.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#endif
#include <unistd.h>
#endif
>From d00d28ae68c731efe6f9392000be9822ee74ff0a Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Wed, 26 Mar 2025 04:08:23 -0500
Subject: [PATCH 43/55] First time attach resolution
---
.../Plugins/Process/AIX/NativeProcessAIX.cpp | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
index fc84763857453..83b8ae5eb3258 100644
--- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
@@ -2000,7 +2000,21 @@ Status NativeProcessAIX::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
} else if (req == PT_WRITE_BLOCK) {
ptrace64(req, pid, (long long)addr, (int)data_size, (int *)result);
} else if (req == PT_ATTACH) {
+ // Block SIGCHLD signal during attach to the process,
+ // to prevent interruptions.
+ // The ptrace operation may send SIGCHLD signals in certain cases
+ // during the attach, which can interfere.
+ static sigset_t signal_set;
+ sigemptyset (&signal_set);
+ sigaddset (&signal_set, SIGCHLD);
+ if(!pthread_sigmask( SIG_BLOCK, &signal_set, NULL))
+ LLDB_LOG(log,"NativeProcessAIX::pthread_sigmask(SIG_BLOCK) Failed");
+
ptrace64(req, pid, 0, 0, nullptr);
+
+ //Unblocking the SIGCHLD after attach work.
+ if(!pthread_sigmask( SIG_UNBLOCK, &signal_set, NULL ))
+ LLDB_LOG(log,"NativeProcessAIX::pthread_sigmask(SIG_UNBLOCK) Failed");
} else if (req == PT_WATCH) {
ptrace64(req, pid, (long long)addr, (int)data_size, nullptr);
} else if (req == PT_DETACH) {
>From 9ff945e62a906e9711022bf8f77b86a0aa05c64e Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Tue, 1 Apr 2025 04:54:51 -0500
Subject: [PATCH 44/55] Invalid DWARF rangelist
---
lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
index cf11e5fb8f5a3..65bd1ee9781d8 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
@@ -578,6 +578,7 @@ SectionType ObjectFileXCOFF::GetSectionType(llvm::StringRef sect_name,
.Case(".dwinfo", eSectionTypeDWARFDebugInfo)
.Case(".dwline", eSectionTypeDWARFDebugLine)
.Case(".dwabrev", eSectionTypeDWARFDebugAbbrev)
+ .Case(".dwrnges", eSectionTypeDWARFDebugRanges)
.Default(eSectionTypeInvalid);
if (section_type != eSectionTypeInvalid)
>From b443dd5b26354da73cd4d785a093d9d1582b25a8 Mon Sep 17 00:00:00 2001
From: Dhruv Srivastava <dhruv.srivastava at ibm.com>
Date: Wed, 2 Apr 2025 11:57:28 +0530
Subject: [PATCH 45/55] Fix for stack memory access from core file (#40)
* Fix for stack memory access in core file
---
.../Process/aix-core/ProcessAIXCore.cpp | 74 ++++++++++++++++++-
.../Plugins/Process/aix-core/ProcessAIXCore.h | 11 +++
2 files changed, 84 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
index cfcbe1a216116..bb2db66e2980e 100644
--- a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
+++ b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.cpp
@@ -94,6 +94,33 @@ ProcessAIXCore::~ProcessAIXCore() {
Finalize(true /* destructing */);
}
+lldb::addr_t ProcessAIXCore::AddAddressRanges(AIXCORE::AIXCore64Header header) {
+ const lldb::addr_t addr = header.StackBaseAddr;
+ FileRange file_range(header.StackOffset, header.StackSize);
+ VMRangeToFileOffset::Entry range_entry(addr, header.StackSize, file_range);
+
+ if (header.StackSize > 0) {
+ VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
+ if (last_entry &&
+ last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
+ last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
+ last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
+ last_entry->SetRangeEnd(range_entry.GetRangeEnd());
+ last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
+ } else {
+ m_core_aranges.Append(range_entry);
+ }
+ }
+
+ const uint32_t permissions = lldb::ePermissionsReadable |
+ lldb::ePermissionsWritable;
+
+ m_core_range_infos.Append(
+ VMRangeToPermissions::Entry(addr, header.StackSize, permissions));
+
+ return addr;
+}
+
bool ProcessAIXCore::CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) {
@@ -170,6 +197,7 @@ Status ProcessAIXCore::DoLoadCore() {
}
FileSpec file = m_core_module_sp->GetObjectFile()->GetFileSpec();
+ Log *log = GetLog(LLDBLog::Process);
if (file) {
const size_t header_size = sizeof(AIXCORE::AIXCore64Header);
@@ -180,6 +208,9 @@ Status ProcessAIXCore::DoLoadCore() {
DataExtractor data(data_sp, lldb::eByteOrderBig, 4);
lldb::offset_t data_offset = 0;
m_aixcore_header.ParseCoreHeader(data, &data_offset);
+ lldb::addr_t addr = AddAddressRanges(m_aixcore_header);
+ if (addr == LLDB_INVALID_ADDRESS)
+ LLDB_LOGF(log, "ProcessAIXCore: Invalid base address. Stack information will be limited");
auto dyld = static_cast<DynamicLoaderAIXDYLD *>(GetDynamicLoader());
dyld->FillCoreLoaderData(data, m_aixcore_header.LoaderOffset,
m_aixcore_header.LoaderSize);
@@ -246,7 +277,48 @@ size_t ProcessAIXCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
}
size_t ProcessAIXCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
- Status &error) { return 0; }
+ Status &error) {
+ ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+ if (core_objfile == nullptr)
+ return 0;
+ // Get the address range
+ const VMRangeToFileOffset::Entry *address_range =
+ m_core_aranges.FindEntryThatContains(addr);
+ if (address_range == nullptr || address_range->GetRangeEnd() < addr) {
+ error = Status::FromErrorStringWithFormat(
+ "core file does not contain 0x%" PRIx64, addr);
+ return 0;
+ }
+
+ // Convert the address into core file offset
+ const lldb::addr_t offset = addr - address_range->GetRangeBase();
+ const lldb::addr_t file_start = address_range->data.GetRangeBase();
+ const lldb::addr_t file_end = address_range->data.GetRangeEnd();
+ size_t bytes_to_read = size; // Number of bytes to read from the core file
+ size_t bytes_copied = 0; // Number of bytes actually read from the core file
+ // Number of bytes available in the core file from the given address
+ lldb::addr_t bytes_left = 0;
+
+ // Don't proceed if core file doesn't contain the actual data for this
+ // address range.
+ if (file_start == file_end)
+ return 0;
+
+ // Figure out how many on-disk bytes remain in this segment starting at the
+ // given offset
+ if (file_end > file_start + offset)
+ bytes_left = file_end - (file_start + offset);
+
+ if (bytes_to_read > bytes_left)
+ bytes_to_read = bytes_left;
+
+ // If there is data available on the core file read it
+ if (bytes_to_read)
+ bytes_copied =
+ core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
+
+ return bytes_copied;
+}
Status ProcessAIXCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
MemoryRegionInfo ®ion_info) {
diff --git a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h
index 9880c491689ca..ffd9e401ee192 100644
--- a/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h
+++ b/lldb/source/Plugins/Process/aix-core/ProcessAIXCore.h
@@ -85,11 +85,22 @@ class ProcessAIXCore : public lldb_private::PostMortemProcess {
void ParseAIXCoreFile();
+ lldb::addr_t AddAddressRanges(AIXCORE::AIXCore64Header header);
private:
lldb::ModuleSP m_core_module_sp;
std::string m_dyld_plugin_name;
+ typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
+ typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange>
+ VMRangeToFileOffset;
+ typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t>
+ VMRangeToPermissions;
+
+ // Address ranges found in the core
+ VMRangeToFileOffset m_core_aranges;
+ VMRangeToPermissions m_core_range_infos;
+
// True if m_thread_contexts contains valid entries
bool m_thread_data_valid = false;
AIXCORE::AIXCore64Header m_aixcore_header;
>From 96db5e3257436a222ee38049528d682166421fa1 Mon Sep 17 00:00:00 2001
From: Dhruv-Srivastava <dhruv.srivastava at ibm.com>
Date: Wed, 2 Apr 2025 01:46:46 -0500
Subject: [PATCH 46/55] Build fail: SBMutex
---
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 0045edf6743d1..2c8f2d583c054 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -83,6 +83,7 @@ add_lldb_library(liblldb STATIC ${option_framework}
SBMemoryRegionInfoList.cpp
SBModule.cpp
SBModuleSpec.cpp
+ SBMutex.cpp
SBPlatform.cpp
SBProcess.cpp
SBProgress.cpp
>From d7a892ef207cde5430021b8705279cc08dc4e0f7 Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Wed, 30 Apr 2025 04:53:28 -0500
Subject: [PATCH 47/55] Added change for step command issue
---
.../Plugins/Process/AIX/NativeProcessAIX.cpp | 87 +++++++++++++------
1 file changed, 61 insertions(+), 26 deletions(-)
diff --git a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
index 83b8ae5eb3258..ace9e11927bee 100644
--- a/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeProcessAIX.cpp
@@ -19,7 +19,7 @@
#include <sstream>
#include <string>
#include <unordered_map>
-
+#include <sys/procfs.h>
#include "NativeThreadAIX.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
//#include "Plugins/Process/Utility/LinuxProcMaps.h"
@@ -79,6 +79,7 @@ using namespace lldb_private;
using namespace lldb_private::process_aix;
using namespace llvm;
+typedef std::function<bool(llvm::Expected<MemoryRegionInfo>)> AIXMapCallback;
// Private bits we only need internally.
static bool ProcessVmReadvSupported() {
@@ -988,13 +989,6 @@ Status NativeProcessAIX::GetMemoryRegionInfo(lldb::addr_t load_addr,
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()) {
@@ -1029,9 +1023,59 @@ Status NativeProcessAIX::GetMemoryRegionInfo(lldb::addr_t load_addr,
return error;
}
+// Parsing the AIX map file /proc/PID/map
+// The map file contains an array of prmap structures
+// which has all the information like size, startaddress, object name, permissions
+bool ParseAIXMapRegions(const char *aix_map, AIXMapCallback const &callback) {
+ MemoryRegionInfo region;
+ struct prmap *prmapData = (struct prmap *)aix_map;
+ struct prmap *entry;
+ uint32_t perm_flag;
+
+ for(entry = prmapData;!(entry->pr_size == 0 && entry->pr_vaddr == NULL); entry++) {
+ const char *o_name = aix_map + entry->pr_pathoff;
+ lldb::addr_t start_address = (lldb::addr_t )entry->pr_vaddr;
+ lldb::addr_t end_address = start_address + entry->pr_size;
+ region.GetRange().SetRangeBase(start_address);
+ region.GetRange().SetRangeEnd(end_address);
+ region.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
+ perm_flag = entry->pr_mflags;
+
+ if(perm_flag & MA_READ)
+ region.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
+ else
+ region.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
+
+ if(perm_flag & MA_WRITE)
+ region.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
+ else
+ region.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
+
+ if(perm_flag & MA_EXEC)
+ region.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
+ else
+ region.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
+
+ if((perm_flag & MA_SLIBTEXT) || (perm_flag & MA_SLIBDATA))
+ region.SetShared(MemoryRegionInfo::OptionalBool::eYes);
+ else if ((perm_flag & MA_PLIBTEXT) || (perm_flag & MA_PLIBDATA))
+ region.SetShared(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ region.SetShared(MemoryRegionInfo::OptionalBool::eDontKnow);
+
+ if(o_name)
+ region.SetName(o_name);
+
+ callback(region);
+ region.Clear();
+ }
+
+ return true;
+}
+
+
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()) {
@@ -1041,7 +1085,7 @@ Status NativeProcessAIX::PopulateMemoryRegionCache() {
}
Status Result;
-#if 0
+
AIXMapCallback callback = [&](llvm::Expected<MemoryRegionInfo> Info) {
if (Info) {
FileSpec file_spec(Info->GetName().GetCString());
@@ -1050,26 +1094,17 @@ Status NativeProcessAIX::PopulateMemoryRegionCache() {
return true;
}
- Result = Info.takeError();
+ Result = Status::FromError(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);
- }
+ auto BufferOrError = getProcFile(GetID(), "map");
+ if (BufferOrError) {
+ std::unique_ptr<llvm::MemoryBuffer> MapBuffer = std::move(*BufferOrError);
+ ParseAIXMapRegions(MapBuffer->getBufferStart(), callback);
+ }
if (Result.Fail())
return Result;
@@ -1090,7 +1125,7 @@ Status NativeProcessAIX::PopulateMemoryRegionCache() {
// We support memory retrieval, remember that.
m_supports_mem_region = LazyBool::eLazyBoolYes;
-#endif
+
return Status();
}
>From 09e392a16dba25a5a8ddccf7893289a0a8798a3b Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Wed, 14 May 2025 00:52:06 -0500
Subject: [PATCH 48/55] Removing netbsd license dependency
---
lldb/source/Host/common/Host.cpp | 165 ++-----------------------------
1 file changed, 7 insertions(+), 158 deletions(-)
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 6cf1112511c3f..7444163366fe5 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -349,168 +349,16 @@ bool Host::ResolveExecutableInBundle(FileSpec &file) { return false; }
#include <stdio.h>
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 <sys/ldr.h>
-#include <errno.h>
-
-/* 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;
#ifdef _AIX
+ // TODO: As the current AIX LLDB is static, we don't need dladdr which is
+ // only for shared library, Below is the hack to find the module name
+ // for static LLDB
+ // FIXME: If LLDB is later built as shared library, we have to find the way simillar to dladdr
+ // since AIX does not support the dladdr API.
if (host_addr == reinterpret_cast<void *>(HostInfoBase::ComputeSharedLibraryDirectory)) {
// FIXME: AIX dladdr return "lldb" for this case
if (p_xargv[0]) {
@@ -519,7 +367,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
return module_filespec;
}
}
-#endif
+#else
#if !defined(__ANDROID__)
Dl_info info;
if (::dladdr(host_addr, &info)) {
@@ -528,6 +376,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
FileSystem::Instance().Resolve(module_filespec);
}
}
+#endif
#endif
return module_filespec;
}
>From b158b8788fa6bf0e13d02373ce9de0d62a4a6aba Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Fri, 16 May 2025 00:51:25 -0500
Subject: [PATCH 49/55] Removed netbsd license files
---
lldb/NOTICE.TXT | 7 -
.../source/Host/common/LICENSE.aix-netbsd.txt | 125 ------------------
2 files changed, 132 deletions(-)
delete mode 100644 lldb/NOTICE.TXT
delete mode 100644 lldb/source/Host/common/LICENSE.aix-netbsd.txt
diff --git a/lldb/NOTICE.TXT b/lldb/NOTICE.TXT
deleted file mode 100644
index d814272967476..0000000000000
--- a/lldb/NOTICE.TXT
+++ /dev/null
@@ -1,7 +0,0 @@
-
-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
diff --git a/lldb/source/Host/common/LICENSE.aix-netbsd.txt b/lldb/source/Host/common/LICENSE.aix-netbsd.txt
deleted file mode 100644
index 9601ab43575f9..0000000000000
--- a/lldb/source/Host/common/LICENSE.aix-netbsd.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-
- 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 at 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 at cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh at cryptsoft.com).
- *
- */
-
- Original SSLeay License
- -----------------------
-
-/* Copyright (C) 1995-1998 Eric Young (eay at cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay at 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 at 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 at 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 at 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.]
- */
-
>From c6d2bc2fa330214c9ae5ab1841d8b724b5dec2f4 Mon Sep 17 00:00:00 2001
From: HemangGadhavi <hemang.gadhavi at ibm.com>
Date: Fri, 16 May 2025 04:57:09 -0500
Subject: [PATCH 50/55] Get base address for each moudle for image list command
---
lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
index cf11e5fb8f5a3..2e19577f2bf8b 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
@@ -717,7 +717,8 @@ lldb_private::Address ObjectFileXCOFF::GetEntryPointAddress() {
}
lldb_private::Address ObjectFileXCOFF::GetBaseAddress() {
- return lldb_private::Address();
+ // Get base address of the section
+ return Address(GetSectionList()->GetSectionAtIndex(0), 0);
}
ObjectFile::Type ObjectFileXCOFF::CalculateType() {
>From 8dd3bd995bf08e50d89a21f7c3bf227ed856798a Mon Sep 17 00:00:00 2001
From: Dhruv Srivastava <dhruv.srivastava at ibm.com>
Date: Fri, 16 May 2025 18:05:57 +0530
Subject: [PATCH 51/55] Fix for GetName() (#61)
Need to access process/main-thread name from psinfo on aix rather than comm on linux.
(0) root @ unobosdev002: /home/dhruv/dio_fs/LLDB/build-lldb
# bin/lldb ../tests/1
(lldb) target create "../tests/1"
Current executable set to '/home/dhruv/dio_fs/LLDB/tests/1' (powerpc64).
(lldb) b main
Breakpoint 1: where = 1`main + 8 at 1.c:3, address = 0x0000000100000928
(lldb) r
Process 44433678 launched: '/home/dhruv/dio_fs/LLDB/tests/1' (powerpc64)
Process 44433678 stopped
* thread #1, name = '1', stop reason = breakpoint 1.1
frame #0: 0x0000000100000928 1`main at 1.c:3
1 int main()
2 {
-> 3 int x = 10;
4 x++;
5 return x;
6 }
(lldb) thread info
thread #1: tid = 0x2a6010e, 0x0000000100000928 1`main at 1.c:3, name = '1', stop reason = breakpoint 1.1
---
lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp
index bb14b6ab4a05e..337caa7c750e8 100644
--- a/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp
+++ b/lldb/source/Plugins/Process/AIX/NativeThreadAIX.cpp
@@ -24,7 +24,8 @@
#include "llvm/ADT/SmallString.h"
#include "Plugins/Process/POSIX/CrashReason.h"
-
+#include <procinfo.h>
+#include <sys/procfs.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <signal.h>
@@ -102,11 +103,15 @@ NativeThreadAIX::NativeThreadAIX(NativeProcessAIX &process,
std::string NativeThreadAIX::GetName() {
NativeProcessAIX &process = GetProcess();
-
- auto BufferOrError = getProcFile(process.GetID(), GetID(), "comm");
+ auto BufferOrError = getProcFile(process.GetID(), "psinfo");
if (!BufferOrError)
return "";
- return std::string(BufferOrError.get()->getBuffer().rtrim('\n'));
+ auto &Buffer = *BufferOrError;
+ if (Buffer->getBufferSize() < sizeof(psinfo_t))
+ return "";
+ const psinfo_t *psinfo =
+ reinterpret_cast<const psinfo_t *>(Buffer->getBufferStart());
+ return std::string(psinfo->pr_fname);
}
lldb::StateType NativeThreadAIX::GetState() { return m_state; }
>From 2e0029cd3afb8bba9ed8c16048214a11db353b1f Mon Sep 17 00:00:00 2001
From: Ravindra Shinde <Ravindra.Shinde2 at ibm.com>
Date: Fri, 16 May 2025 03:28:24 -0500
Subject: [PATCH 52/55] Global variables are not accessed correctly
1188732:lldb, print command does not works properly sometimes
Signed-off-by: Ravindra Shinde <Ravindra.Shinde2 at ibm.com>
---
.../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 20 +++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
index cf11e5fb8f5a3..e544417ee4c61 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
@@ -325,6 +325,7 @@ bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value,
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;
@@ -333,16 +334,19 @@ bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value,
// 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 (section_sp && !section_sp->IsThreadSpecific()) {
+ addr_t load_addr = 0;
+ if (!value_is_offset)
+ load_addr = section_sp->GetFileAddress();
+ else {
+ if (strcmp(section_sp->GetName().AsCString(), ".text") == 0)
+ load_addr = section_sp->GetFileOffset() + value;
+ else /* Other sections: data, bss, loader, dwline, dwinfo, dwabrev */
+ load_addr = section_sp->GetFileAddress() + value;
+ }
if (target.GetSectionLoadListPublic().SetSectionLoadAddress(
- section_sp, (use_offset ?
- (section_sp->GetFileOffset() + value) : (section_sp->GetFileAddress() + value))))
+ section_sp, load_addr))
++num_loaded_sections;
}
}
>From e0952b5841148298a5ae7242bb0a7f951b2f9d14 Mon Sep 17 00:00:00 2001
From: DhruvSrivastavaX <dhruv.srivastava at ibm.com>
Date: Mon, 9 Jun 2025 05:17:27 -0500
Subject: [PATCH 53/55] Stabilizing the branch to fix forced-update issue -
Linked to Recent PRs for aix/Host.cpp, aix/Support.cpp etc
---
lldb/include/lldb/Host/aix/Support.h | 9 -
lldb/source/Host/aix/Host.cpp | 257 ++++++++-------------------
2 files changed, 74 insertions(+), 192 deletions(-)
diff --git a/lldb/include/lldb/Host/aix/Support.h b/lldb/include/lldb/Host/aix/Support.h
index 7be0c9ac98c67..f02a1904b09fa 100644
--- a/lldb/include/lldb/Host/aix/Support.h
+++ b/lldb/include/lldb/Host/aix/Support.h
@@ -18,15 +18,6 @@ namespace lldb_private {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file);
-<<<<<<< HEAD
-llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
-getProcFile(::pid_t pid, const llvm::Twine &file);
-
-llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
-getProcFile(const llvm::Twine &file);
-
-=======
->>>>>>> upstream/main
} // namespace lldb_private
#endif // #ifndef LLDB_HOST_AIX_SUPPORT_H
diff --git a/lldb/source/Host/aix/Host.cpp b/lldb/source/Host/aix/Host.cpp
index 9680af52598af..b5572b93d93a9 100644
--- a/lldb/source/Host/aix/Host.cpp
+++ b/lldb/source/Host/aix/Host.cpp
@@ -6,37 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ScopedPrinter.h"
-
+#include "lldb/Host/Host.h"
+#include "lldb/Host/posix/Support.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/posix/Support.h"
-#include "lldb/Utility/DataExtractor.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include <dirent.h>
#include <sys/proc.h>
#include <sys/procfs.h>
-using namespace llvm;
using namespace lldb;
using namespace lldb_private;
@@ -55,173 +35,98 @@ enum class ProcessState {
};
}
-namespace lldb_private {
-class ProcessLaunchInfo;
+static ProcessInstanceInfo::timespec convert(pr_timestruc64_t t) {
+ ProcessInstanceInfo::timespec ts;
+ ts.tv_sec = t.tv_sec;
+ ts.tv_usec = t.tv_nsec / 1000; // nanos to micros
+ return ts;
}
-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");
+static bool GetStatusInfo(::pid_t pid, ProcessInstanceInfo &processInfo,
+ ProcessState &State) {
+ struct pstatus pstatusData;
+ 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<ProcessState>(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;
-}
+ std::unique_ptr<llvm::MemoryBuffer> StatusBuffer = std::move(*BufferOrError);
+ // Ensure there's enough data for psinfoData
+ if (StatusBuffer->getBufferSize() < sizeof(pstatusData))
+ return false;
-static bool IsDirNumeric(const char *dname) {
- for (; *dname; dname++) {
- if (!isdigit(*dname))
- return false;
+ std::memcpy(&pstatusData, StatusBuffer->getBufferStart(),
+ sizeof(pstatusData));
+ switch (pstatusData.pr_stat) {
+ case SIDL:
+ State = ProcessState::Idle;
+ break;
+ case SACTIVE:
+ State = ProcessState::Running;
+ break;
+ case SSTOP:
+ State = ProcessState::TracedOrStopped;
+ break;
+ case SZOMB:
+ State = ProcessState::Zombie;
+ break;
+ default:
+ State = ProcessState::Unknown;
+ break;
}
+ processInfo.SetIsZombie(State == ProcessState::Zombie);
+ processInfo.SetUserTime(convert(pstatusData.pr_utime));
+ processInfo.SetSystemTime(convert(pstatusData.pr_stime));
+ processInfo.SetCumulativeUserTime(convert(pstatusData.pr_cutime));
+ processInfo.SetCumulativeSystemTime(convert(pstatusData.pr_cstime));
return true;
}
-static void GetProcessArgs(::pid_t pid, ProcessInstanceInfo &process_info) {
- auto BufferOrError = getProcFile(pid, "cmdline");
- if (!BufferOrError)
- return;
- std::unique_ptr<llvm::MemoryBuffer> 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');
+static bool GetExePathAndIds(::pid_t pid, ProcessInstanceInfo &process_info) {
struct psinfo psinfoData;
+ auto BufferOrError = getProcFile(pid, "psinfo");
+ if (!BufferOrError)
+ return false;
- // 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);
- }
-}
+ std::unique_ptr<llvm::MemoryBuffer> PsinfoBuffer = std::move(*BufferOrError);
+ // Ensure there's enough data for psinfoData
+ if (PsinfoBuffer->getBufferSize() < sizeof(psinfoData))
+ return false;
-static void GetProcessEnviron(::pid_t pid, ProcessInstanceInfo &process_info) {
- // Get the process environment.
- auto BufferOrError = getProcFile(pid, "environ");
- if (!BufferOrError)
- return;
+ std::memcpy(&psinfoData, PsinfoBuffer->getBufferStart(), sizeof(psinfoData));
+ llvm::StringRef PathRef(
+ psinfoData.pr_psargs,
+ strnlen(psinfoData.pr_psargs, sizeof(psinfoData.pr_psargs)));
+ if (PathRef.empty())
+ return false;
- std::unique_ptr<llvm::MemoryBuffer> 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);
- }
+ process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
+ ArchSpec arch_spec = ArchSpec();
+ arch_spec.SetArchitecture(eArchTypeXCOFF, llvm::XCOFF::TCPU_PPC64,
+ LLDB_INVALID_CPUTYPE, llvm::Triple::AIX);
+ process_info.SetArchitecture(arch_spec);
+ process_info.SetParentProcessID(psinfoData.pr_ppid);
+ process_info.SetGroupID(psinfoData.pr_gid);
+ process_info.SetEffectiveGroupID(psinfoData.pr_egid);
+ process_info.SetUserID(psinfoData.pr_uid);
+ process_info.SetEffectiveUserID(psinfoData.pr_euid);
+ process_info.SetProcessGroupID(psinfoData.pr_pgid);
+ process_info.SetProcessSessionID(psinfoData.pr_sid);
+ return true;
}
static bool GetProcessAndStatInfo(::pid_t pid,
ProcessInstanceInfo &process_info,
- ProcessState &State, ::pid_t &tracerpid) {
- ::pid_t tgid;
- tracerpid = 0;
+ ProcessState &State) {
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))
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return false;
+ // Get Executable path/Arch and Get User and Group IDs.
+ if (!GetExePathAndIds(pid, process_info))
+ return false;
+ // Get process status and timing info.
+ if (!GetStatusInfo(pid, process_info, State))
return false;
return true;
@@ -270,24 +175,10 @@ uint32_t Host::FindProcessesImpl(const ProcessInstanceInfoMatch &match_info,
}
bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
- ::pid_t tracerpid;
ProcessState State;
- return GetProcessAndStatInfo(pid, process_info, State, tracerpid);
+ return GetProcessAndStatInfo(pid, process_info, State);
}
-Environment Host::GetEnvironment() { return Environment(environ); }
-
Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
return Status("unimplemented");
}
-
-std::optional<lldb::pid_t> 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;
-}
>From c12d50c4d2e63cc2a21ed18da1f794e1e9dbce17 Mon Sep 17 00:00:00 2001
From: Dhruv Srivastava <dhruv.srivastava at ibm.com>
Date: Mon, 9 Jun 2025 21:28:58 +0530
Subject: [PATCH 54/55] Re-Design for ObjectFileXCOFF - 64/32 bit (#72)
This is the New design for the ObjectFileXCOFF using LLVM interfaces.
The intent for which I had to implement this is that
we don't need to create new structures and can use LLVM interfaces instead, which makes the code cleaner,
safer and more structured.
And community was not accepting the older design.
As a plus, I have also made sure that it is able to handle 32 bit binaries too along with 64 bit
I have discarded the older design and only kept whats necessary, without changing any existing behaviour.
Most of this code has already been reviewed and merged in the community,
so I am pulling it together again here in our fork branch.
---
.../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 516 +++++-------------
.../ObjectFile/XCOFF/ObjectFileXCOFF.h | 132 +----
2 files changed, 167 insertions(+), 481 deletions(-)
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
index 4d363915ddacd..349b3a9d5e619 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp
@@ -49,9 +49,6 @@ using namespace lldb;
using namespace lldb_private;
LLDB_PLUGIN_DEFINE(ObjectFileXCOFF)
-
-char ObjectFileXCOFF::ID;
-
// FIXME: target 64bit at this moment.
// Static methods.
@@ -98,7 +95,6 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp,
return nullptr;
if (!objfile_up->ParseHeader())
- //FIXME objfile leak
return nullptr;
UGLY_FLAG_FOR_AIX = true;
@@ -111,16 +107,17 @@ bool ObjectFileXCOFF::CreateBinary() {
Log *log = GetLog(LLDBLog::Object);
- auto binary = llvm::object::ObjectFile::createObjectFile(
- llvm::MemoryBufferRef(toStringRef(m_data.GetData()),
- m_file.GetFilename().GetStringRef()),
- file_magic::xcoff_object_64);
+ auto memory_ref = llvm::MemoryBufferRef(toStringRef(m_data.GetData()),
+ m_file.GetFilename().GetStringRef());
+ llvm::file_magic magic = llvm::identify_magic(memory_ref.getBuffer());
+
+ auto binary = llvm::object::ObjectFile::createObjectFile(memory_ref, magic);
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.
+ // Make sure we only handle XCOFF format.
m_binary =
llvm::unique_dyn_cast<llvm::object::XCOFFObjectFile>(std::move(*binary));
if (!m_binary)
@@ -159,9 +156,9 @@ size_t ObjectFileXCOFF::GetModuleSpecifications(
static uint32_t XCOFFHeaderSizeFromMagic(uint32_t magic) {
switch (magic) {
- // TODO: 32bit not supported.
- // case XCOFF::XCOFF32:
- // return sizeof(struct llvm::object::XCOFFFileHeader32);
+ case XCOFF::XCOFF32:
+ return sizeof(struct llvm::object::XCOFFFileHeader32);
+ break;
case XCOFF::XCOFF64:
return sizeof(struct llvm::object::XCOFFFileHeader64);
break;
@@ -185,137 +182,9 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp,
}
bool ObjectFileXCOFF::ParseHeader() {
- ModuleSP module_sp(GetModule());
- if (module_sp) {
- std::lock_guard<std::recursive_mutex> 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<DataBufferHeap>(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;
+ if (m_binary->is64Bit())
+ return m_binary->fileHeader64()->Magic == XCOFF::XCOFF64;
+ return m_binary->fileHeader32()->Magic == XCOFF::XCOFF32;
}
bool ObjectFileXCOFF::SetLoadAddress(Target &target, lldb::addr_t value,
@@ -397,10 +266,8 @@ ByteOrder ObjectFileXCOFF::GetByteOrder() const { return eByteOrderBig; }
bool ObjectFileXCOFF::IsExecutable() const { return true; }
uint32_t ObjectFileXCOFF::GetAddressByteSize() const {
- if (m_xcoff_header.magic == XCOFF::XCOFF64)
+ if (m_binary->is64Bit())
return 8;
- else if (m_xcoff_header.magic == XCOFF::XCOFF32)
- return 4;
return 4;
}
@@ -408,190 +275,147 @@ AddressClass ObjectFileXCOFF::GetAddressClass(addr_t file_addr) {
return AddressClass::eUnknown;
}
-lldb::SymbolType ObjectFileXCOFF::MapSymbolType(llvm::object::SymbolRef::Type sym_type) {
+lldb::SymbolType 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;
+ else if (sym_type == llvm::object::SymbolRef::ST_File)
+ return lldb::eSymbolTypeSourceFile;
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<StringRef> 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<llvm::object::SymbolRef::Type> 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()));
+ SectionList *sectionList = GetSectionList();
+
+ for (const auto &symbol_ref : m_binary->symbols()) {
+ llvm::object::XCOFFSymbolRef xcoff_sym_ref(symbol_ref);
+ llvm::Expected<llvm::StringRef> name_or_err = xcoff_sym_ref.getName();
+ if (!name_or_err) {
+ consumeError(name_or_err.takeError());
+ continue;
+ }
+ llvm::StringRef symbolName = name_or_err.get();
+ // Remove the dot prefix for demangle
+ llvm::StringRef symbol_name =
+ symbolName.starts_with(".") ? symbolName.drop_front() : symbolName;
+ auto storageClass = xcoff_sym_ref.getStorageClass();
+ if (storageClass == XCOFF::C_HIDEXT && symbolName != "TOC") {
+ if (xcoff_sym_ref.getNumberOfAuxEntries() != 1)
+ continue;
+ auto aux_csect_or_err = xcoff_sym_ref.getXCOFFCsectAuxRef();
+ if (!aux_csect_or_err) {
+ consumeError(aux_csect_or_err.takeError());
+ continue;
}
- ++sidx;
+ const llvm::object::XCOFFCsectAuxRef csect_aux = aux_csect_or_err.get();
+ if (csect_aux.getStorageMappingClass() != XCOFF::XMC_PR ||
+ (m_binary->is64Bit() ? (csect_aux.getAuxType64() != XCOFF::AUX_CSECT)
+ : false))
+ continue;
+ }
- if (symbol.naux > 0) {
- i += symbol.naux;
- offset += symbol.naux * symbol_size;
- }
+ Symbol symbol;
+ symbol.GetMangled().SetValue(ConstString(symbol_name));
+
+ int16_t sectionNumber = xcoff_sym_ref.getSectionNumber();
+ size_t sectionIndex = static_cast<size_t>(sectionNumber - 1);
+ if (sectionNumber > 0 && sectionIndex < sectionList->GetSize()) {
+ lldb::SectionSP section_sp =
+ sectionList->GetSectionAtIndex(sectionNumber - 1);
+ if (!section_sp || section_sp->GetFileAddress() == LLDB_INVALID_ADDRESS)
+ continue;
+ lldb::addr_t file_addr = section_sp->GetFileAddress();
+ lldb::addr_t symbolValue = xcoff_sym_ref.getValue();
+ if (symbolValue < file_addr)
+ continue;
+ symbol.GetAddressRef() = Address(section_sp, symbolValue - file_addr);
+ }
+
+ Expected<llvm::object::SymbolRef::Type> sym_type_or_err =
+ symbol_ref.getType();
+ if (!sym_type_or_err) {
+ consumeError(sym_type_or_err.takeError());
+ continue;
}
- lldb_symtab.Resize(sidx);
+
+ symbol.SetType(MapSymbolType(sym_type_or_err.get()));
+
+ lldb_symtab.AddSymbol(symbol);
}
}
-bool ObjectFileXCOFF::IsStripped() {
- return false;
-}
+bool ObjectFileXCOFF::IsStripped() { return false; }
void ObjectFileXCOFF::CreateSections(SectionList &unified_section_list) {
+
if (m_sections_up)
return;
+
m_sections_up = std::make_unique<SectionList>();
- ModuleSP module_sp(GetModule());
- if (module_sp) {
- std::lock_guard<std::recursive_mutex> 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);
- }
- }
+ if (m_binary->is64Bit())
+ CreateSectionsWithBitness<XCOFF64>(unified_section_list);
+ else
+ CreateSectionsWithBitness<XCOFF32>(unified_section_list);
}
-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<lldb::offset_t>(XCOFF::SymbolTableEntrySize)) + stroff;
- if (const char *name = m_data.GetCStr(&string_file_offset))
- return name;
- return "";
- }
- return hdr_name;
+template <typename T>
+static auto GetSections(llvm::object::XCOFFObjectFile *binary) {
+ if constexpr (T::Is64Bit)
+ return binary->sections64();
+ else
+ return binary->sections32();
}
-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<SectionType>(sect_name)
- .Case(".dwinfo", eSectionTypeDWARFDebugInfo)
- .Case(".dwline", eSectionTypeDWARFDebugLine)
- .Case(".dwabrev", eSectionTypeDWARFDebugAbbrev)
- .Default(eSectionTypeInvalid);
-
- if (section_type != eSectionTypeInvalid)
- return section_type;
+template <typename T>
+void ObjectFileXCOFF::CreateSectionsWithBitness(
+ SectionList &unified_section_list) {
+ ModuleSP module_sp(GetModule());
+ if (!module_sp)
+ return;
+
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+
+ int idx = 0;
+ for (const typename T::SectionHeader §ion :
+ GetSections<T>(m_binary.get())) {
+
+ ConstString const_sect_name(section.Name);
+
+ SectionType section_type = lldb::eSectionTypeOther;
+ if (section.Flags & XCOFF::STYP_TEXT)
+ section_type = eSectionTypeCode;
+ else if (section.Flags & XCOFF::STYP_DATA)
+ section_type = eSectionTypeData;
+ else if (section.Flags & XCOFF::STYP_BSS)
+ section_type = eSectionTypeZeroFill;
+ else if (section.Flags & XCOFF::STYP_DWARF) {
+ section_type = llvm::StringSwitch<SectionType>(section.Name)
+ .Case(".dwinfo", eSectionTypeDWARFDebugInfo)
+ .Case(".dwline", eSectionTypeDWARFDebugLine)
+ .Case(".dwabrev", eSectionTypeDWARFDebugAbbrev)
+ .Case(".dwrnges", eSectionTypeDWARFDebugRanges)
+ .Default(eSectionTypeInvalid);
+ }
+
+ SectionSP section_sp(new Section(
+ module_sp, this, ++idx, const_sect_name, section_type,
+ section.VirtualAddress, section.SectionSize,
+ section.FileOffsetToRawData, section.SectionSize, 0, section.Flags));
+
+ uint32_t permissions = ePermissionsReadable;
+ if (section.Flags & (XCOFF::STYP_DATA | XCOFF::STYP_BSS))
+ permissions |= ePermissionsWritable;
+ if (section.Flags & XCOFF::STYP_TEXT)
+ permissions |= ePermissionsExecutable;
+
+ section_sp->SetPermissions(permissions);
+ m_sections_up->AddSection(section_sp);
+ unified_section_list.AddSection(section_sp);
}
- return eSectionTypeOther;
}
-void ObjectFileXCOFF::Dump(Stream *s) {
-}
+void ObjectFileXCOFF::Dump(Stream *s) {}
ArchSpec ObjectFileXCOFF::GetArchitecture() {
ArchSpec arch_spec =
@@ -630,54 +454,6 @@ uint32_t ObjectFileXCOFF::ParseDependentModules() {
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<std::string, std::vector<std::string>>::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<std::string>();
- iter = m_deps_base_members.find(std::string(Basename));
- }
- iter->second.push_back(std::string(CurrentStr));
- }
- }
-#endif
return m_deps_filespec->GetSize();
}
@@ -703,7 +479,8 @@ lldb_private::Address ObjectFileXCOFF::GetEntryPointAddress() {
return m_entry_point_address;
SectionList *section_list = GetSectionList();
- addr_t vm_addr = m_xcoff_aux_header.EntryPointAddr;
+ addr_t vm_addr = m_binary->is64Bit() ? m_binary->auxiliaryHeader64()->EntryPointAddr :
+ m_binary->auxiliaryHeader32()->EntryPointAddr;
SectionSP section_sp(
section_list->FindSectionContainingFileAddress(vm_addr));
if (section_sp) {
@@ -726,9 +503,13 @@ lldb_private::Address ObjectFileXCOFF::GetBaseAddress() {
}
ObjectFile::Type ObjectFileXCOFF::CalculateType() {
- if (m_binary->fileHeader64()->Flags & XCOFF::F_EXEC)
+
+ const auto flags = m_binary->is64Bit() ? m_binary->fileHeader64()->Flags
+ : m_binary->fileHeader32()->Flags;
+
+ if (flags & XCOFF::F_EXEC)
return eTypeExecutable;
- else if (m_binary->fileHeader64()->Flags & XCOFF::F_SHROBJ)
+ else if (flags & XCOFF::F_SHROBJ)
return eTypeSharedLibrary;
return eTypeUnknown;
}
@@ -758,23 +539,18 @@ ObjectFileXCOFF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
}
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));
+ 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) {
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));
-}
+ DataBufferSP header_data_sp,
+ const lldb::ProcessSP &process_sp,
+ addr_t header_addr)
+ : ObjectFile(module_sp, process_sp, header_addr, header_data_sp) {}
diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
index f827fca3932f4..ce4bcaa16df5a 100644
--- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
+++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h
@@ -56,18 +56,9 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
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;
@@ -113,126 +104,45 @@ class ObjectFileXCOFF : public lldb_private::ObjectFile {
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);
+ 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);
+ 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<LoadableData>
- 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 §);
-
+ std::vector<LoadableData>
+ GetLoadableData(lldb_private::Target &target) override;
uint32_t ParseDependentModules();
- typedef std::vector<section_header_t> SectionHeaderColl;
+
private:
bool CreateBinary();
+ template <typename T>
+ void
+ CreateSectionsWithBitness(lldb_private::SectionList &unified_section_list);
+
+ struct XCOFF32 {
+ using SectionHeader = llvm::object::XCOFFSectionHeader32;
+ static constexpr bool Is64Bit = false;
+ };
+ struct XCOFF64 {
+ using SectionHeader = llvm::object::XCOFFSectionHeader64;
+ static constexpr bool Is64Bit = true;
+ };
- xcoff_header_t m_xcoff_header;
- xcoff_aux_header_t m_xcoff_aux_header;
- SectionHeaderColl m_sect_headers;
std::unique_ptr<llvm::object::XCOFFObjectFile> m_binary;
lldb_private::Address m_entry_point_address;
std::optional<lldb_private::FileSpecList> m_deps_filespec;
>From 0b6893565d6d36a1cae68d8f283e9f6a037c8652 Mon Sep 17 00:00:00 2001
From: DhruvSrivastavaX <dhruv.srivastava at ibm.com>
Date: Fri, 13 Jun 2025 01:55:00 -0500
Subject: [PATCH 55/55] Merge typo
---
lldb/source/Target/RegisterContextUnwind.cpp | 57 --------------------
1 file changed, 57 deletions(-)
diff --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index f6e3b568dfe4d..85016ed417d0c 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -1520,65 +1520,8 @@ RegisterContextUnwind::SavedLocationForRegister(
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
-<<<<<<< HEAD
- if (!have_unwindplan_regloc) {
- // If the UnwindPlan failed to give us an unwind location for this
- // register, we may be able to fall back to some ABI-defined default. For
- // example, some ABIs allow to determine the caller's SP via the CFA. Also,
- // the ABI may set volatile registers to the undefined state.
- ABI *abi = process ? process->GetABI().get() : nullptr;
- if (abi) {
- const RegisterInfo *reg_info =
- GetRegisterInfoAtIndex(regnum.GetAsKind(eRegisterKindLLDB));
- if (reg_info &&
- abi->GetFallbackRegisterLocation(reg_info, unwindplan_regloc)) {
- UnwindLogMsg(
- "supplying caller's saved %s (%d)'s location using ABI default",
- regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
- have_unwindplan_regloc = true;
- }
- }
- }
-
- if (!have_unwindplan_regloc) {
- if (IsFrameZero()) {
- // This is frame 0 - we should return the actual live register context
- // value
- lldb_private::UnwindLLDB::ConcreteRegisterLocation new_regloc;
- new_regloc.type =
- UnwindLLDB::ConcreteRegisterLocation::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 "
- "RegisterContext at frame 0",
- regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB));
- return UnwindLLDB::RegisterSearchResult::eRegisterFound;
- } else {
- std::string unwindplan_name;
- if (m_full_unwind_plan_sp) {
- unwindplan_name += "via '";
- unwindplan_name += m_full_unwind_plan_sp->GetSourceName().AsCString();
- unwindplan_name += "'";
- }
- UnwindLogMsg("no save location for %s (%d) %s", regnum.GetName(),
- regnum.GetAsKind(eRegisterKindLLDB),
- unwindplan_name.c_str());
- }
- return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
- }
-
- // unwindplan_regloc has valid contents about where to retrieve the register
- if (unwindplan_regloc.IsUnspecified()) {
-=======
// abs_regloc has valid contents about where to retrieve the register
if (abs_regloc->IsUnspecified()) {
->>>>>>> upstream/main
lldb_private::UnwindLLDB::ConcreteRegisterLocation new_regloc = {};
new_regloc.type = UnwindLLDB::ConcreteRegisterLocation::eRegisterNotSaved;
m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = new_regloc;
More information about the lldb-commits
mailing list