[lldb] [POSIX-DYLD] Update the cached exe path after attach

Fix the POSIX-DYLD plugin to update the cached executable path after
attaching.  Previously, the path was cached in DYLDRendezvous
constructor and not updated afterwards.  This meant that if LLDB was
attaching to a process (e.g. via connecting to lldb-server), the code
stored the empty path before DidAttach() resolved it.  The fix updates
the cached path in DidAttach().

This fixes a new instance of https://llvm.org/pr17880

Differential Revision: https://reviews.llvm.org/D92264
This commit is contained in:
Michał Górny 2020-11-28 11:11:01 +01:00
parent 8666b9057f
commit dbfdb139f7
5 changed files with 39 additions and 3 deletions

View File

@ -94,12 +94,13 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
: m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_current(),
m_previous(), m_loaded_modules(), m_soentries(), m_added_soentries(),
m_removed_soentries() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
m_thread_info.valid = false;
UpdateExecutablePath();
}
// Cache a copy of the executable path
void DYLDRendezvous::UpdateExecutablePath() {
if (m_process) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
if (exe_mod) {
m_exe_file_spec = exe_mod->GetPlatformFileSpec();

View File

@ -60,6 +60,9 @@ public:
DYLDRendezvous(lldb_private::Process *process);
/// Update the cached executable path.
void UpdateExecutablePath();
/// Update the internal snapshot of runtime linker rendezvous and recompute
/// the currently loaded modules.
///

View File

@ -102,6 +102,7 @@ void DynamicLoaderPOSIXDYLD::DidAttach() {
ModuleSP executable_sp = GetTargetExecutable();
ResolveExecutableModule(executable_sp);
m_rendezvous.UpdateExecutablePath();
// find the main process load offset
addr_t load_offset = ComputeLoadOffset();

View File

@ -20,6 +20,13 @@ class ProcessAttachTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
# Find the line number to break for main.c.
self.line = line_number('main.cpp',
'// Waiting to be attached...')
@skipIfiOSSimulator
def test_attach_to_process_by_id(self):
"""Test attach by process id"""
@ -77,6 +84,28 @@ class ProcessAttachTestCase(TestBase):
process = target.GetProcess()
self.assertTrue(process, PROCESS_IS_VALID)
def test_attach_to_process_by_id_correct_executable_offset(self):
"""
Test that after attaching to a process the executable offset
is determined correctly on FreeBSD. This is a regression test
for dyld plugin getting the correct executable path,
and therefore being able to identify it in the module list.
"""
self.build()
exe = self.getBuildArtifact(exe_name)
# In order to reproduce, we must spawn using a relative path
popen = self.spawnSubprocess(os.path.relpath(exe))
self.runCmd("process attach -p " + str(popen.pid))
# Make suer we did not attach to early
lldbutil.run_break_set_by_file_and_line(
self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False)
self.runCmd("process continue")
self.expect("p g_val", substrs=["$0 = 12345"])
def tearDown(self):
# Destroy process before TestBase.tearDown()
self.dbg.GetSelectedTarget().GetProcess().Destroy()

View File

@ -3,6 +3,8 @@
#include <chrono>
#include <thread>
volatile int g_val = 12345;
int main(int argc, char const *argv[]) {
int temp;
lldb_enable_attach();