[Lldb-commits] [lldb] 01450dd - Change debugserver to report the cpu(sub)type of process, not the host.
Adrian Prantl via lldb-commits
lldb-commits at lists.llvm.org
Mon Feb 26 09:57:16 PST 2024
Author: Adrian Prantl
Date: 2024-02-26T09:57:07-08:00
New Revision: 01450dd1c69d1edb0d01159352a56c99988839f4
URL: https://github.com/llvm/llvm-project/commit/01450dd1c69d1edb0d01159352a56c99988839f4
DIFF: https://github.com/llvm/llvm-project/commit/01450dd1c69d1edb0d01159352a56c99988839f4.diff
LOG: Change debugserver to report the cpu(sub)type of process, not the host.
This way debugserver can correctly report qProcessInfo for arm64
processes on arm64e-capable hosts.
Patch implemented with help from Jason Molenda!
Added:
Modified:
lldb/source/Target/Target.cpp
lldb/test/API/macosx/arm64e-attach/Makefile
lldb/test/API/macosx/arm64e-attach/TestArm64eAttach.py
lldb/tools/debugserver/source/DNB.cpp
lldb/tools/debugserver/source/DNB.h
lldb/tools/debugserver/source/MacOSX/MachProcess.h
lldb/tools/debugserver/source/MacOSX/MachProcess.mm
lldb/tools/debugserver/source/RNBRemote.cpp
Removed:
################################################################################
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index e982a30a3ae4ff..089915cab4915a 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -33,6 +33,7 @@
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/PosixApi.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -1571,6 +1572,13 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform,
if (m_arch.GetSpec().GetTriple() == other.GetTriple())
replace_local_arch = false;
+ // Workaround for for pre-2024 debugserver, which always
+ // returns arm64e on arm64e-capable hardware regardless of
+ // what the process is. This can be deleted at some point in
+ // the future.
+ if (!m_arch.GetSpec().GetMachOCPUSubType() &&
+ other.GetMachOCPUSubType() == llvm::MachO::CPU_SUBTYPE_ARM64E)
+ replace_local_arch = true;
}
}
}
diff --git a/lldb/test/API/macosx/arm64e-attach/Makefile b/lldb/test/API/macosx/arm64e-attach/Makefile
index c9319d6e6888a4..b24dccd7c02ad4 100644
--- a/lldb/test/API/macosx/arm64e-attach/Makefile
+++ b/lldb/test/API/macosx/arm64e-attach/Makefile
@@ -1,2 +1,7 @@
C_SOURCES := main.c
+
+# Uncomment this for local debugging.
+#all:
+# xcrun clang -g $(SRCDIR)/main.c -o a.out -target arm64e-apple-macosx
+
include Makefile.rules
diff --git a/lldb/test/API/macosx/arm64e-attach/TestArm64eAttach.py b/lldb/test/API/macosx/arm64e-attach/TestArm64eAttach.py
index 0dc8700ed02dd8..3ec977b507b890 100644
--- a/lldb/test/API/macosx/arm64e-attach/TestArm64eAttach.py
+++ b/lldb/test/API/macosx/arm64e-attach/TestArm64eAttach.py
@@ -13,10 +13,12 @@ def test(self):
# Skip this test if not running on AArch64 target that supports PAC
if not self.isAArch64PAuth():
self.skipTest("Target must support pointer authentication.")
+
self.build()
popen = self.spawnSubprocess(self.getBuildArtifact(), [])
- error = lldb.SBError()
+
# This simulates how Xcode attaches to a process by pid/name.
+ error = lldb.SBError()
target = self.dbg.CreateTarget("", "arm64", "", True, error)
listener = lldb.SBListener("my.attach.listener")
process = target.AttachToProcessWithID(listener, popen.pid, error)
@@ -24,5 +26,10 @@ def test(self):
self.assertTrue(process, PROCESS_IS_VALID)
self.assertEqual(target.GetTriple().split('-')[0], "arm64e",
"target triple is updated correctly")
+
+ self.expect('process plugin packet send qProcessInfo',
+ "debugserver returns correct triple",
+ substrs=['cputype:100000c', 'cpusubtype:2', 'ptrsize:8'])
+
error = process.Kill()
self.assertSuccess(error)
diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp
index 0ec50df42d1fed..1ac9a8040c6163 100644
--- a/lldb/tools/debugserver/source/DNB.cpp
+++ b/lldb/tools/debugserver/source/DNB.cpp
@@ -1062,6 +1062,14 @@ DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid,
return INVALID_NUB_ADDRESS;
}
+std::optional<std::pair<cpu_type_t, cpu_subtype_t>>
+DNBGetMainBinaryCPUTypes(nub_process_t pid) {
+ MachProcessSP procSP;
+ if (GetProcessSP(pid, procSP))
+ return procSP->GetMainBinaryCPUTypes(pid);
+ return {};
+}
+
JSONGenerator::ObjectSP
DNBGetAllLoadedLibrariesInfos(nub_process_t pid, bool report_load_commands) {
MachProcessSP procSP;
diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h
index 97de83ef9ff80d..10d1f687943556 100644
--- a/lldb/tools/debugserver/source/DNB.h
+++ b/lldb/tools/debugserver/source/DNB.h
@@ -210,6 +210,8 @@ DNBGetTSDAddressForThread(nub_process_t pid, nub_thread_t tid,
uint64_t plo_pthread_tsd_base_address_offset,
uint64_t plo_pthread_tsd_base_offset,
uint64_t plo_pthread_tsd_entry_size);
+std::optional<std::pair<cpu_type_t, cpu_subtype_t>>
+DNBGetMainBinaryCPUTypes(nub_process_t pid);
JSONGenerator::ObjectSP
DNBGetAllLoadedLibrariesInfos(nub_process_t pid, bool report_load_commands);
JSONGenerator::ObjectSP
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
index 8432bdb36c0cf8..db673693a1b21a 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h
@@ -103,6 +103,8 @@ class MachProcess {
const char *stdin_path, const char *stdout_path, const char *stderr_path,
bool no_stdio, MachProcess *process, int disable_aslr, DNBError &err);
nub_addr_t GetDYLDAllImageInfosAddress();
+ std::optional<std::pair<cpu_type_t, cpu_subtype_t>>
+ GetMainBinaryCPUTypes(nub_process_t pid);
static const void *PrepareForAttach(const char *path,
nub_launch_flavor_t launch_flavor,
bool waitfor, DNBError &err_str);
diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm
index 3a4dfb9ea6ea22..87bdbf835bfd10 100644
--- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm
+++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm
@@ -1111,6 +1111,23 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
return FormatDynamicLibrariesIntoJSON(image_infos, report_load_commands);
}
+std::optional<std::pair<cpu_type_t, cpu_subtype_t>>
+MachProcess::GetMainBinaryCPUTypes(nub_process_t pid) {
+ int pointer_size = GetInferiorAddrSize(pid);
+ std::vector<struct binary_image_information> image_infos;
+ GetAllLoadedBinariesViaDYLDSPI(image_infos);
+ uint32_t platform = GetPlatform();
+ for (auto &image_info : image_infos)
+ if (GetMachOInformationFromMemory(platform, image_info.load_address,
+ pointer_size, image_info.macho_info))
+ if (image_info.macho_info.mach_header.filetype == MH_EXECUTE)
+ return {
+ {static_cast<cpu_type_t>(image_info.macho_info.mach_header.cputype),
+ static_cast<cpu_subtype_t>(
+ image_info.macho_info.mach_header.cpusubtype)}};
+ return {};
+}
+
// Fetch information about the shared libraries at the given load addresses
// using the
// dyld SPIs that exist in macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer.
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index feea4c914ec536..03d427d3fc5954 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -6195,59 +6195,14 @@ rnb_err_t RNBRemote::HandlePacket_qSymbol(const char *command) {
}
}
-// Note that all numeric values returned by qProcessInfo are hex encoded,
-// including the pid and the cpu type.
-
-rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
- nub_process_t pid;
- std::ostringstream rep;
-
- // If we haven't run the process yet, return an error.
- if (!m_ctx.HasValidProcessID())
- return SendPacket("E68");
-
- pid = m_ctx.ProcessID();
-
- rep << "pid:" << std::hex << pid << ';';
-
- int procpid_mib[4];
- procpid_mib[0] = CTL_KERN;
- procpid_mib[1] = KERN_PROC;
- procpid_mib[2] = KERN_PROC_PID;
- procpid_mib[3] = pid;
- struct kinfo_proc proc_kinfo;
- size_t proc_kinfo_size = sizeof(struct kinfo_proc);
-
- if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
- if (proc_kinfo_size > 0) {
- rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
- rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
- << ';';
- rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
- << ';';
- rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
- << ';';
- if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
- rep << "effective-gid:" << std::hex
- << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
- }
- }
-
+static std::pair<cpu_type_t, cpu_subtype_t>
+GetCPUTypesFromHost(nub_process_t pid) {
cpu_type_t cputype = DNBProcessGetCPUType(pid);
if (cputype == 0) {
DNBLog("Unable to get the process cpu_type, making a best guess.");
cputype = best_guess_cpu_type();
}
- uint32_t addr_size = 0;
- if (cputype != 0) {
- rep << "cputype:" << std::hex << cputype << ";";
- if (cputype & CPU_ARCH_ABI64)
- addr_size = 8;
- else
- addr_size = 4;
- }
-
bool host_cpu_is_64bit = false;
uint32_t is64bit_capable;
size_t is64bit_capable_len = sizeof(is64bit_capable);
@@ -6288,14 +6243,69 @@ rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
if (cputype == CPU_TYPE_ARM64_32 && cpusubtype == 2)
cpusubtype = CPU_SUBTYPE_ARM64_32_V8;
#endif
+ }
+
+ return {cputype, cpusubtype};
+}
+
+// Note that all numeric values returned by qProcessInfo are hex encoded,
+// including the pid and the cpu type.
+rnb_err_t RNBRemote::HandlePacket_qProcessInfo(const char *p) {
+ nub_process_t pid;
+ std::ostringstream rep;
+
+ // If we haven't run the process yet, return an error.
+ if (!m_ctx.HasValidProcessID())
+ return SendPacket("E68");
+
+ pid = m_ctx.ProcessID();
+
+ rep << "pid:" << std::hex << pid << ';';
+
+ int procpid_mib[4];
+ procpid_mib[0] = CTL_KERN;
+ procpid_mib[1] = KERN_PROC;
+ procpid_mib[2] = KERN_PROC_PID;
+ procpid_mib[3] = pid;
+ struct kinfo_proc proc_kinfo;
+ size_t proc_kinfo_size = sizeof(struct kinfo_proc);
+
+ if (::sysctl(procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
+ if (proc_kinfo_size > 0) {
+ rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ';';
+ rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid
+ << ';';
+ rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid
+ << ';';
+ rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid
+ << ';';
+ if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
+ rep << "effective-gid:" << std::hex
+ << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ';';
+ }
+ }
+
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ if (auto cputypes = DNBGetMainBinaryCPUTypes(pid))
+ std::tie(cputype, cpusubtype) = *cputypes;
+ else
+ std::tie(cputype, cpusubtype) = GetCPUTypesFromHost(pid);
+
+ uint32_t addr_size = 0;
+ if (cputype != 0) {
+ rep << "cputype:" << std::hex << cputype << ";";
rep << "cpusubtype:" << std::hex << cpusubtype << ';';
+ if (cputype & CPU_ARCH_ABI64)
+ addr_size = 8;
+ else
+ addr_size = 4;
}
bool os_handled = false;
if (addr_size > 0) {
rep << "ptrsize:" << std::dec << addr_size << ';';
-
#if defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1
// Try and get the OS type by looking at the load commands in the main
// executable and looking for a LC_VERSION_MIN load command. This is the
More information about the lldb-commits
mailing list