https://github.com/clayborg created https://github.com/llvm/llvm-project/pull/210807
Getting the process info from ProcessELFCore would always return the information from the prpsinfo.pr_psargs from the NT_PRPSINFO. This meant if the process was launched with a symlink, the process info would always claim the main executable was the symlink. We want the process info's executable to always be the resolved executable when possible. The DynamicLoaderPOSIXDYLD was using the process info to load the main executable if it wasn't set, or it was comparing if the main executable's module spec matched the process info, and if it didn't match it would end up trying to load the main executable using the process info. We also ask for the UUID from the process before trying to use the process info to replace the executable in DynamicLoaderPOSIXDYLD::ResolveExecutableModule(). >From 1855dde725ec93aba003742df6a36b5c0a28fb25 Mon Sep 17 00:00:00 2001 From: Greg Clayton <[email protected]> Date: Mon, 20 Jul 2026 13:49:35 -0700 Subject: [PATCH] Fix ProcessELFCore::GetProcessInfo() to return expected results. Getting the process info from ProcessELFCore would always return the information from the prpsinfo.pr_psargs from the NT_PRPSINFO. This meant if the process was launched with a symlink, the process info would always claim the main executable was the symlink. We want the process info's executable to always be the resolved executable when possible. The DynamicLoaderPOSIXDYLD was using the process info to load the main executable if it wasn't set, or it was comparing if the main executable's module spec matched the process info, and if it didn't match it would end up trying to load the main executable using the process info. We also ask for the UUID from the process before trying to use the process info to replace the executable in DynamicLoaderPOSIXDYLD::ResolveExecutableModule(). --- lldb/include/lldb/API/SBProcessInfo.h | 4 ++ lldb/source/API/SBProcessInfo.cpp | 9 +++++ .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 5 +++ .../Process/elf-core/ProcessElfCore.cpp | 26 ++++++++++++- .../postmortem/elf-core/TestLinuxCore.py | 38 +++++++++++++++++-- 5 files changed, 77 insertions(+), 5 deletions(-) diff --git a/lldb/include/lldb/API/SBProcessInfo.h b/lldb/include/lldb/API/SBProcessInfo.h index b3120bf5374ee..408ee85dfecab 100644 --- a/lldb/include/lldb/API/SBProcessInfo.h +++ b/lldb/include/lldb/API/SBProcessInfo.h @@ -30,6 +30,10 @@ class LLDB_API SBProcessInfo { SBFileSpec GetExecutableFile(); + /// If the process was laumched with a first argument that doesn't match + /// the executable file or name, this will return a valid string. + const char *GetArg0(); + lldb::pid_t GetProcessID(); uint32_t GetUserID(); diff --git a/lldb/source/API/SBProcessInfo.cpp b/lldb/source/API/SBProcessInfo.cpp index d9ff526ad2aca..4e0f73ae5b010 100644 --- a/lldb/source/API/SBProcessInfo.cpp +++ b/lldb/source/API/SBProcessInfo.cpp @@ -73,6 +73,15 @@ SBFileSpec SBProcessInfo::GetExecutableFile() { return file_spec; } +const char *SBProcessInfo::GetArg0() { + LLDB_INSTRUMENT_VA(this); + + if (!m_opaque_up) + return nullptr; + + return ConstString(m_opaque_up->GetArg0()).GetCString(); +} + lldb::pid_t SBProcessInfo::GetProcessID() { LLDB_INSTRUMENT_VA(this); diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 6db4d99ccbdba..70d24c45552dd 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -997,6 +997,11 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule( ModuleSpec module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); + // See if the process has UUID info for the executable. If this is a core + // file we really want the UUID in the module spec so we don't load a + // random executable with the same name from the current system and ignore + // the required UUID. + m_process->FindModuleUUID(module_spec); if (module_sp && module_sp->MatchesModuleSpec(module_spec)) return; diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index ced84ab829772..4cc760de54a5c 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -1238,13 +1238,35 @@ bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) { info.Clear(); info.SetProcessID(GetID()); info.SetArchitecture(GetArchitecture()); + ModuleSpec exe_module_spec; + bool added_executable = false; lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); + const bool add_exe_file_as_first_arg = true; if (module_sp) { - const bool add_exe_file_as_first_arg = false; info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), add_exe_file_as_first_arg); + added_executable = true; + } else { + ModuleSpec exe_module_spec; + if (GetMainExecutableModuleSpec(exe_module_spec)) { + if (exe_module_spec.GetFileSpec()) { + info.SetExecutableFile(exe_module_spec.GetFileSpec(), + add_exe_file_as_first_arg); + added_executable = true; + } + } + } + Args process_args = m_process_args.as_args(); + bool first_arg_is_executable = true; + if (added_executable) { + // Strip the executable name from the process args as it can be a symlink + // that doesn't match the executable we would have created from a call to + // GetMainExecutableModuleSpec(...). + first_arg_is_executable = false; + info.SetArg0(process_args.GetArgumentAtIndex(0)); + process_args.DeleteArgumentAtIndex(0); } - info.SetArguments(m_process_args.as_args(), /*first_arg_is_executable=*/true); + info.SetArguments(process_args, first_arg_is_executable); return true; } diff --git a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py index fc79ae98e5b73..7d01a2ffc81a7 100644 --- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py +++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -1453,7 +1453,17 @@ def test_exe_name_extraction_nt_file(self): target = self.dbg.CreateTarget(None) process = target.LoadCore(core_path) exe_module = target.modules[0] - self.assertEqual(exe_module.GetFileSpec().fullpath, "/path/nt_file_foo") + exe_path = "/path/nt_file_foo" + symlink_path = "/path/prpsinfo_foo" + self.assertEqual(exe_module.GetFileSpec().fullpath, exe_path) + + # Verify that the process info is correct. + process_info = target.process.GetProcessInfo() + self.assertEqual(process_info.GetName(), 'nt_file_foo') + self.assertEqual(process_info.GetArg0(), symlink_path) + self.assertEqual(process_info.GetExecutableFile().fullpath, exe_path) + self.assertEqual(process_info.GetNumArguments(), 1) + self.assertEqual(process_info.GetArgumentAtIndex(0), '--verbose') self.dbg.DeleteTarget(target) @skipIfLLVMTargetMissing("X86") @@ -1472,7 +1482,18 @@ def test_exe_name_extraction_at_execfn(self): target = self.dbg.CreateTarget(None) process = target.LoadCore(core_path) exe_module = target.modules[0] - self.assertEqual(exe_module.GetFileSpec().fullpath, "/path/execfn_foo") + exe_path = "/path/execfn_foo" + symlink_path = "/path/prpsinfo_foo" + self.assertEqual(exe_module.GetFileSpec().fullpath, exe_path) + + # Verify that the process info is correct. + process_info = target.process.GetProcessInfo() + self.assertEqual(process_info.GetName(), 'execfn_foo') + self.assertEqual(process_info.GetArg0(), symlink_path) + self.assertEqual(process_info.GetExecutableFile().fullpath, exe_path) + self.assertEqual(process_info.GetNumArguments(), 1) + self.assertEqual(process_info.GetArgumentAtIndex(0), '--verbose') + self.dbg.DeleteTarget(target) @skipIfLLVMTargetMissing("X86") @@ -1488,7 +1509,18 @@ def test_exe_name_extraction_nt_prpsinfo(self): target = self.dbg.CreateTarget(None) process = target.LoadCore(core_path) exe_module = target.modules[0] - self.assertEqual(exe_module.GetFileSpec().fullpath, "prpsinfo_foo") + exe_path = 'prpsinfo_foo' + symlink_path = "/path/prpsinfo_foo" + self.assertEqual(exe_module.GetFileSpec().fullpath, exe_path) + + process_info = target.process.GetProcessInfo() + self.assertEqual(process_info.GetName(), exe_path) + self.assertEqual(process_info.GetArg0(), symlink_path) + self.assertEqual(process_info.GetExecutableFile().fullpath, exe_path) + self.assertEqual(process_info.GetNumArguments(), 1) + self.assertEqual(process_info.GetArgumentAtIndex(0), '--verbose') + + self.dbg.DeleteTarget(target) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
