[Lldb-commits] [lldb] [lldb][DynamicLoader] Fix lldb unable to stop at _dl_debug_state if user set it before the process launched. (PR #88792)
Zequan Wu via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 17 10:13:11 PDT 2024
https://github.com/ZequanWu updated https://github.com/llvm/llvm-project/pull/88792
>From 26528cd679478448edf446e0e82e5f207ffd6113 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Mon, 15 Apr 2024 16:30:38 -0400
Subject: [PATCH 1/4] [lldb][DynamicLoader] Fix lldb unable to stop at
_dl_debug_state if user set it before the process launched.
---
lldb/include/lldb/Target/Target.h | 3 +++
.../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 5 +++++
lldb/source/Target/Target.cpp | 17 ++++++++++-------
.../breakpoint_command/TestBreakpointCommand.py | 17 +++++++++++++++++
4 files changed, 35 insertions(+), 7 deletions(-)
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 2c2e6b2831ccee..3554ef0ea5a140 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -878,6 +878,9 @@ class Target : public std::enable_shared_from_this<Target>,
// the address of its previous instruction and return that address.
lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr);
+ void UpdateBreakpoints(ModuleList &module_list, bool added,
+ bool delete_locations);
+
void ModulesDidLoad(ModuleList &module_list);
void ModulesDidUnload(ModuleList &module_list, bool delete_locations);
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 9baf86da4dc799..901fa53682da8e 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -576,6 +576,11 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
false);
m_interpreter_module = module_sp;
+ // Manually update breakpoints after updating loaded sections, because they
+ // cannot be resolve at the time when creating this module.
+ ModuleList module_list;
+ module_list.Append(module_sp);
+ m_process->GetTarget().UpdateBreakpoints(module_list, true, false);
return module_sp;
}
return nullptr;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 09b0ac42631d1a..ec2dea5cc238d3 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -1687,6 +1687,13 @@ void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) {
ModulesDidUnload(module_list, false);
}
+void Target::UpdateBreakpoints(ModuleList &module_list, bool added,
+ bool delete_locations) {
+ m_breakpoint_list.UpdateBreakpoints(module_list, added, delete_locations);
+ m_internal_breakpoint_list.UpdateBreakpoints(module_list, added,
+ delete_locations);
+}
+
void Target::ModulesDidLoad(ModuleList &module_list) {
const size_t num_images = module_list.GetSize();
if (m_valid && num_images) {
@@ -1694,8 +1701,7 @@ void Target::ModulesDidLoad(ModuleList &module_list) {
ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
LoadScriptingResourceForModule(module_sp, this);
}
- m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
- m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
+ UpdateBreakpoints(module_list, true, false);
if (m_process_sp) {
m_process_sp->ModulesDidLoad(module_list);
}
@@ -1713,8 +1719,7 @@ void Target::SymbolsDidLoad(ModuleList &module_list) {
}
}
- m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
- m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
+ UpdateBreakpoints(module_list, true, false);
auto data_sp =
std::make_shared<TargetEventData>(shared_from_this(), module_list);
BroadcastEvent(eBroadcastBitSymbolsLoaded, data_sp);
@@ -1727,9 +1732,7 @@ void Target::ModulesDidUnload(ModuleList &module_list, bool delete_locations) {
auto data_sp =
std::make_shared<TargetEventData>(shared_from_this(), module_list);
BroadcastEvent(eBroadcastBitModulesUnloaded, data_sp);
- m_breakpoint_list.UpdateBreakpoints(module_list, false, delete_locations);
- m_internal_breakpoint_list.UpdateBreakpoints(module_list, false,
- delete_locations);
+ UpdateBreakpoints(module_list, false, delete_locations);
// If a module was torn down it will have torn down the 'TypeSystemClang's
// that we used as source 'ASTContext's for the persistent variables in
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index ea242952e409ec..a7e23fae14a21f 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -671,3 +671,20 @@ def test_breakpoint_statistics_hitcount(self):
self.assertNotEqual(breakpoints_stats, None)
for breakpoint_stats in breakpoints_stats:
self.assertIn("hitCount", breakpoint_stats)
+
+ @skipIf(oslist=no_match(["linux"]))
+ def test_break_at__dl_debug_state(self):
+ """
+ Test lldb is able to stop at _dl_debug_state if it is set before the
+ process is launched.
+ """
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ self.runCmd("target create %s" % exe)
+ bpid = lldbutil.run_break_set_by_symbol(self, "_dl_debug_state",
+ num_expected_locations=0)
+ self.runCmd("run")
+ self.assertIsNotNone(
+ lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(),
+ bpid)
+ )
>From 29d5861f1748c2f71c9d699b670dc393a9bf6710 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 16 Apr 2024 11:45:35 -0400
Subject: [PATCH 2/4] format
---
.../breakpoint_command/TestBreakpointCommand.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index a7e23fae14a21f..850235fdcefa70 100644
--- a/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/lldb/test/API/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -681,10 +681,10 @@ def test_break_at__dl_debug_state(self):
self.build()
exe = self.getBuildArtifact("a.out")
self.runCmd("target create %s" % exe)
- bpid = lldbutil.run_break_set_by_symbol(self, "_dl_debug_state",
- num_expected_locations=0)
+ bpid = lldbutil.run_break_set_by_symbol(
+ self, "_dl_debug_state", num_expected_locations=0
+ )
self.runCmd("run")
self.assertIsNotNone(
- lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(),
- bpid)
+ lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), bpid)
)
>From 735b8d22f763c38d6e5833dd56a6bf29f84325be Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 16 Apr 2024 14:13:18 -0400
Subject: [PATCH 3/4] Update to use `Target::ModulesDidLoad`.
---
lldb/include/lldb/Target/Target.h | 3 ---
.../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 6 ++----
lldb/source/Target/Target.cpp | 17 +++++++----------
.../TestModuleLoadedNotifys.py | 10 +++++++++-
4 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 3554ef0ea5a140..2c2e6b2831ccee 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -878,9 +878,6 @@ class Target : public std::enable_shared_from_this<Target>,
// the address of its previous instruction and return that address.
lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr);
- void UpdateBreakpoints(ModuleList &module_list, bool added,
- bool delete_locations);
-
void ModulesDidLoad(ModuleList &module_list);
void ModulesDidUnload(ModuleList &module_list, bool delete_locations);
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 901fa53682da8e..a4fddf2eaae6f1 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -575,12 +575,10 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
true /* notify */)) {
UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
false);
- m_interpreter_module = module_sp;
- // Manually update breakpoints after updating loaded sections, because they
- // cannot be resolve at the time when creating this module.
ModuleList module_list;
module_list.Append(module_sp);
- m_process->GetTarget().UpdateBreakpoints(module_list, true, false);
+ target.ModulesDidLoad(module_list);
+ m_interpreter_module = module_sp;
return module_sp;
}
return nullptr;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index ec2dea5cc238d3..09b0ac42631d1a 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -1687,13 +1687,6 @@ void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) {
ModulesDidUnload(module_list, false);
}
-void Target::UpdateBreakpoints(ModuleList &module_list, bool added,
- bool delete_locations) {
- m_breakpoint_list.UpdateBreakpoints(module_list, added, delete_locations);
- m_internal_breakpoint_list.UpdateBreakpoints(module_list, added,
- delete_locations);
-}
-
void Target::ModulesDidLoad(ModuleList &module_list) {
const size_t num_images = module_list.GetSize();
if (m_valid && num_images) {
@@ -1701,7 +1694,8 @@ void Target::ModulesDidLoad(ModuleList &module_list) {
ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
LoadScriptingResourceForModule(module_sp, this);
}
- UpdateBreakpoints(module_list, true, false);
+ m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
+ m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
if (m_process_sp) {
m_process_sp->ModulesDidLoad(module_list);
}
@@ -1719,7 +1713,8 @@ void Target::SymbolsDidLoad(ModuleList &module_list) {
}
}
- UpdateBreakpoints(module_list, true, false);
+ m_breakpoint_list.UpdateBreakpoints(module_list, true, false);
+ m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false);
auto data_sp =
std::make_shared<TargetEventData>(shared_from_this(), module_list);
BroadcastEvent(eBroadcastBitSymbolsLoaded, data_sp);
@@ -1732,7 +1727,9 @@ void Target::ModulesDidUnload(ModuleList &module_list, bool delete_locations) {
auto data_sp =
std::make_shared<TargetEventData>(shared_from_this(), module_list);
BroadcastEvent(eBroadcastBitModulesUnloaded, data_sp);
- UpdateBreakpoints(module_list, false, delete_locations);
+ m_breakpoint_list.UpdateBreakpoints(module_list, false, delete_locations);
+ m_internal_breakpoint_list.UpdateBreakpoints(module_list, false,
+ delete_locations);
// If a module was torn down it will have torn down the 'TypeSystemClang's
// that we used as source 'ASTContext's for the persistent variables in
diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py b/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py
index abf761fb3420b4..34c1f81316383a 100644
--- a/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py
+++ b/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py
@@ -7,6 +7,7 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
+import re
class ModuleLoadedNotifysTestCase(TestBase):
@@ -70,6 +71,7 @@ def test_launch_notifications(self):
total_modules_added_events = 0
total_modules_removed_events = 0
already_loaded_modules = []
+ ld_name_pattern = re.compile("^ld.*\.so")
while listener.GetNextEvent(event):
if lldb.SBTarget.EventIsTargetEvent(event):
if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded:
@@ -83,8 +85,14 @@ def test_launch_notifications(self):
# will be loaded again when dyld moves itself into the
# shared cache. Use the basename so this also works
# when reading dyld from the expanded shared cache.
+ # On linux, ld.so will be loaded only once, but the
+ # broadcaster event will be sent twice.
+ module.file.basename
exe_basename = lldb.SBFileSpec(exe).basename
- if module.file.basename not in ["dyld", exe_basename]:
+ if module.file.basename not in [
+ "dyld",
+ exe_basename,
+ ] and not ld_name_pattern.match(module.file.basename):
self.assertNotIn(
module,
already_loaded_modules,
>From 7cf26285a4d75a639d4bbdbf361187c809a5569f Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 17 Apr 2024 13:11:55 -0400
Subject: [PATCH 4/4] disable first notification
---
.../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 4 +++-
.../TestModuleLoadedNotifys.py | 10 +---------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index a4fddf2eaae6f1..074cab976e96f9 100644
--- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -572,9 +572,11 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
ModuleSpec module_spec(file, target.GetArchitecture());
if (ModuleSP module_sp = target.GetOrCreateModule(module_spec,
- true /* notify */)) {
+ false /* notify */)) {
UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
false);
+ // Manually notify that dynamic linker is loaded after updating load section
+ // addersses so that breakpoints can be resolved.
ModuleList module_list;
module_list.Append(module_sp);
target.ModulesDidLoad(module_list);
diff --git a/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py b/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py
index 34c1f81316383a..abf761fb3420b4 100644
--- a/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py
+++ b/lldb/test/API/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py
@@ -7,7 +7,6 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-import re
class ModuleLoadedNotifysTestCase(TestBase):
@@ -71,7 +70,6 @@ def test_launch_notifications(self):
total_modules_added_events = 0
total_modules_removed_events = 0
already_loaded_modules = []
- ld_name_pattern = re.compile("^ld.*\.so")
while listener.GetNextEvent(event):
if lldb.SBTarget.EventIsTargetEvent(event):
if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded:
@@ -85,14 +83,8 @@ def test_launch_notifications(self):
# will be loaded again when dyld moves itself into the
# shared cache. Use the basename so this also works
# when reading dyld from the expanded shared cache.
- # On linux, ld.so will be loaded only once, but the
- # broadcaster event will be sent twice.
- module.file.basename
exe_basename = lldb.SBFileSpec(exe).basename
- if module.file.basename not in [
- "dyld",
- exe_basename,
- ] and not ld_name_pattern.match(module.file.basename):
+ if module.file.basename not in ["dyld", exe_basename]:
self.assertNotIn(
module,
already_loaded_modules,
More information about the lldb-commits
mailing list