[Lldb-commits] [lldb] [lldb] Fix source line annotations for libsanitizers traces (PR #154247)
Julian Lettner via lldb-commits
lldb-commits at lists.llvm.org
Wed Aug 20 12:10:20 PDT 2025
https://github.com/yln updated https://github.com/llvm/llvm-project/pull/154247
>From 51480efc86e24eb79a4d95fc79da282828aa1a5f Mon Sep 17 00:00:00 2001
From: Julian Lettner <jlettner at apple.com>
Date: Mon, 18 Aug 2025 12:37:24 -0700
Subject: [PATCH 1/3] [lldb] Introduce HistoryPCType enum
Introduce and adopt `HistoryPCType` enum to replace
`pcs_are_call_addresses` bool to make handling of
history back traces more clear and allow for
extension of behavior.
This change is a mechanical refactoring and
preservers current behavior:
```
pcs_are_call_addresses:
false -> HistoryPCType::Returns (default)
true -> HistoryPCType::Calls
```
rdar://157596927
---
lldb/include/lldb/lldb-private-enumerations.h | 2 ++
.../InstrumentationRuntimeMainThreadChecker.cpp | 6 +++---
.../UBSan/InstrumentationRuntimeUBSan.cpp | 6 +++---
.../Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp | 4 ++--
lldb/source/Plugins/Process/Utility/HistoryThread.cpp | 5 ++---
lldb/source/Plugins/Process/Utility/HistoryThread.h | 6 +++---
lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp | 7 +++----
lldb/source/Plugins/Process/Utility/HistoryUnwind.h | 6 ++----
.../Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp | 6 +++---
9 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h
index 98c1e956bf8f7..d9820c715e6db 100644
--- a/lldb/include/lldb/lldb-private-enumerations.h
+++ b/lldb/include/lldb/lldb-private-enumerations.h
@@ -248,6 +248,8 @@ enum class IterationAction {
Stop,
};
+enum class HistoryPCType { Returns, ReturnsNoZerothFrame, Calls };
+
inline std::string GetStatDescription(lldb_private::StatisticKind K) {
switch (K) {
case StatisticKind::ExpressionSuccessful:
diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
index e67e60b4a3957..b89a6aa176919 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp
@@ -266,9 +266,9 @@ InstrumentationRuntimeMainThreadChecker::GetBacktracesFromExtendedStopInfo(
// We gather symbolication addresses above, so no need for HistoryThread to
// try to infer the call addresses.
- bool pcs_are_call_addresses = true;
- ThreadSP new_thread_sp = std::make_shared<HistoryThread>(
- *process_sp, tid, PCs, pcs_are_call_addresses);
+ auto pc_type = HistoryPCType::Calls;
+ ThreadSP new_thread_sp =
+ std::make_shared<HistoryThread>(*process_sp, tid, PCs, pc_type);
// Save this in the Process' ExtendedThreadList so a strong pointer retains
// the object
diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
index c2db3540a797b..565fd353a98e5 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp
@@ -324,9 +324,9 @@ InstrumentationRuntimeUBSan::GetBacktracesFromExtendedStopInfo(
// We gather symbolication addresses above, so no need for HistoryThread to
// try to infer the call addresses.
- bool pcs_are_call_addresses = true;
- ThreadSP new_thread_sp = std::make_shared<HistoryThread>(
- *process_sp, tid, PCs, pcs_are_call_addresses);
+ auto pc_type = HistoryPCType::Calls;
+ ThreadSP new_thread_sp =
+ std::make_shared<HistoryThread>(*process_sp, tid, PCs, pc_type);
std::string stop_reason_description = GetStopReasonDescription(info);
new_thread_sp->SetName(stop_reason_description.c_str());
diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index afaaa57b09587..3b5840325709b 100644
--- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -131,9 +131,9 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp,
// The ASAN runtime already massages the return addresses into call
// addresses, we don't want LLDB's unwinder to try to locate the previous
// instruction again as this might lead to us reporting a different line.
- bool pcs_are_call_addresses = true;
+ auto pc_type = HistoryPCType::Calls;
HistoryThread *history_thread =
- new HistoryThread(*process_sp, tid, pcs, pcs_are_call_addresses);
+ new HistoryThread(*process_sp, tid, pcs, pc_type);
ThreadSP new_thread_sp(history_thread);
std::ostringstream thread_name_with_number;
thread_name_with_number << thread_name << " Thread " << tid;
diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp
index bc06757c806a9..93efa2a748880 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryThread.cpp
+++ b/lldb/source/Plugins/Process/Utility/HistoryThread.cpp
@@ -27,13 +27,12 @@ using namespace lldb_private;
HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid,
std::vector<lldb::addr_t> pcs,
- bool pcs_are_call_addresses)
+ HistoryPCType pc_type)
: Thread(process, tid, true), m_framelist_mutex(), m_framelist(),
m_pcs(pcs), m_extended_unwind_token(LLDB_INVALID_ADDRESS), m_queue_name(),
m_thread_name(), m_originating_unique_thread_id(tid),
m_queue_id(LLDB_INVALID_QUEUE_ID) {
- m_unwinder_up =
- std::make_unique<HistoryUnwind>(*this, pcs, pcs_are_call_addresses);
+ m_unwinder_up = std::make_unique<HistoryUnwind>(*this, pcs, pc_type);
Log *log = GetLog(LLDBLog::Object);
LLDB_LOGF(log, "%p HistoryThread::HistoryThread", static_cast<void *>(this));
}
diff --git a/lldb/source/Plugins/Process/Utility/HistoryThread.h b/lldb/source/Plugins/Process/Utility/HistoryThread.h
index a66e0f2d4207c..cdc3b090f4848 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryThread.h
+++ b/lldb/source/Plugins/Process/Utility/HistoryThread.h
@@ -27,14 +27,14 @@ namespace lldb_private {
/// process execution
///
/// This subclass of Thread is used to provide a backtrace from earlier in
-/// process execution. It is given a backtrace list of pc addresses and it
-/// will create stack frames for them.
+/// process execution. It is given a backtrace list of pcs (return or call
+/// addresses) and it will create stack frames for them.
class HistoryThread : public lldb_private::Thread {
public:
HistoryThread(lldb_private::Process &process, lldb::tid_t tid,
std::vector<lldb::addr_t> pcs,
- bool pcs_are_call_addresses = false);
+ HistoryPCType pc_type = HistoryPCType::Returns);
~HistoryThread() override;
diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
index 7749dc6f5d514..7d25ec3e21811 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -24,9 +24,8 @@ using namespace lldb_private;
// Constructor
HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs,
- bool pcs_are_call_addresses)
- : Unwind(thread), m_pcs(pcs),
- m_pcs_are_call_addresses(pcs_are_call_addresses) {}
+ HistoryPCType pc_type)
+ : Unwind(thread), m_pcs(pcs), m_pc_type(pc_type) {}
// Destructor
@@ -61,7 +60,7 @@ bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
if (frame_idx < m_pcs.size()) {
cfa = frame_idx;
pc = m_pcs[frame_idx];
- if (m_pcs_are_call_addresses)
+ if (m_pc_type == HistoryPCType::Calls)
behaves_like_zeroth_frame = true;
else
behaves_like_zeroth_frame = (frame_idx == 0);
diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h
index cb72b5d0a1764..3cf70a4255254 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.h
+++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -19,7 +19,7 @@ namespace lldb_private {
class HistoryUnwind : public lldb_private::Unwind {
public:
HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs,
- bool pcs_are_call_addresses = false);
+ HistoryPCType pc_type = HistoryPCType::Returns);
~HistoryUnwind() override;
@@ -36,9 +36,7 @@ class HistoryUnwind : public lldb_private::Unwind {
private:
std::vector<lldb::addr_t> m_pcs;
- /// This boolean indicates that the PCs in the non-0 frames are call
- /// addresses and not return addresses.
- bool m_pcs_are_call_addresses;
+ HistoryPCType m_pc_type;
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
index b23f64210cc80..04a25e4d35d54 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
@@ -544,9 +544,9 @@ ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,
if (!thread_extended_info->ForEach(extract_frame_pc))
return {};
- originating_thread_sp =
- std::make_shared<HistoryThread>(*m_process, real_thread->GetIndexID(),
- app_specific_backtrace_pcs, true);
+ originating_thread_sp = std::make_shared<HistoryThread>(
+ *m_process, real_thread->GetIndexID(), app_specific_backtrace_pcs,
+ HistoryPCType::Calls);
originating_thread_sp->SetQueueName(type.AsCString());
}
return originating_thread_sp;
>From d87f634771c60de23c536ac8e4eafbeef933be80 Mon Sep 17 00:00:00 2001
From: Julian Lettner <jlettner at apple.com>
Date: Mon, 18 Aug 2025 18:01:32 -0700
Subject: [PATCH 2/3] [lldb] Fix source line annotations for libsanitizers
When providing allocation and deallocation traces,
the ASan compiler-rt runtime already provides call
addresses (`HistoryPCType::Calls`).
On Darwin, system sanitizers (libsanitizers)
provides return address. It also discards a few
non-user frames at the top of the stack, because
these internal libmalloc/libsanitizers stack
frames do not provide any value when diagnosing
memory errors.
Introduce and add handling for
`HistoryPCType::ReturnsNoZerothFrame` to cover
this case and enable libsanitizers traces
line-level testing.
rdar://157596927
---
lldb/include/lldb/lldb-private-enumerations.h | 16 ++++++++-
.../MemoryHistory/asan/MemoryHistoryASan.cpp | 34 ++++++++++++-------
.../Plugins/Process/Utility/HistoryUnwind.cpp | 16 ++++++---
.../functionalities/asan/TestMemoryHistory.py | 14 ++++----
4 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h
index d9820c715e6db..cc4657c87cb0f 100644
--- a/lldb/include/lldb/lldb-private-enumerations.h
+++ b/lldb/include/lldb/lldb-private-enumerations.h
@@ -248,7 +248,21 @@ enum class IterationAction {
Stop,
};
-enum class HistoryPCType { Returns, ReturnsNoZerothFrame, Calls };
+/// Specifies the type of PCs when creating a `HistoryThread`.
+/// - `Returns` - Usually, when LLDB unwinds the stack or we retrieve a stack
+/// trace via `backtrace()` we are collecting return addresses (except for the
+/// topmost frame which is the actual PC). LLDB then maps these return
+/// addresses back to call addresses to give accurate source line annotations.
+/// - `ReturnsNoZerothFrame` - Some trace providers (e.g., libsanitizers traces)
+/// collect return addresses but prune the topmost frames, so we should skip
+/// the special treatment of frame 0.
+/// - `Calls` - Other trace providers (e.g., ASan compiler-rt runtime) already
+/// perform this mapping, so we need to prevent LLDB from doing it again.
+enum class HistoryPCType {
+ Returns, ///< PCs are return addresses, except for topmost frame.
+ ReturnsNoZerothFrame, ///< All PCs are return addresses.
+ Calls ///< PCs are call addresses.
+};
inline std::string GetStatDescription(lldb_private::StatisticKind K) {
switch (K) {
diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index 3b5840325709b..ab8de10023e2d 100644
--- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -91,11 +91,9 @@ const char *memory_history_asan_command_format =
t;
)";
-static void CreateHistoryThreadFromValueObject(ProcessSP process_sp,
- ValueObjectSP return_value_sp,
- const char *type,
- const char *thread_name,
- HistoryThreads &result) {
+static void CreateHistoryThreadFromValueObject(
+ ProcessSP process_sp, ValueObjectSP return_value_sp, HistoryPCType pc_type,
+ const char *type, const char *thread_name, HistoryThreads &result) {
std::string count_path = "." + std::string(type) + "_count";
std::string tid_path = "." + std::string(type) + "_tid";
std::string trace_path = "." + std::string(type) + "_trace";
@@ -128,10 +126,6 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp,
pcs.push_back(pc);
}
- // The ASAN runtime already massages the return addresses into call
- // addresses, we don't want LLDB's unwinder to try to locate the previous
- // instruction again as this might lead to us reporting a different line.
- auto pc_type = HistoryPCType::Calls;
HistoryThread *history_thread =
new HistoryThread(*process_sp, tid, pcs, pc_type);
ThreadSP new_thread_sp(history_thread);
@@ -176,10 +170,24 @@ HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {
options.SetAutoApplyFixIts(false);
options.SetLanguage(eLanguageTypeObjC_plus_plus);
+ // The ASan compiler-rt runtime already massages the return addresses into
+ // call addresses, so we don't want LLDB's unwinder to try to locate the
+ // previous instruction again as this might lead to us reporting a different
+ // line.
+ auto pc_type = HistoryPCType::Calls;
+
if (auto m = GetPreferredAsanModule(process_sp->GetTarget())) {
SymbolContextList sc_list;
sc_list.Append(SymbolContext(std::move(m)));
options.SetPreferredSymbolContexts(std::move(sc_list));
+ } else if (process_sp->GetTarget()
+ .GetArchitecture()
+ .GetTriple()
+ .isOSDarwin()) {
+ // Darwin, but not ASan compiler-rt implies libsanitizers which collects
+ // return addresses. It also discards a few non-user frames at the top of
+ // the stack.
+ pc_type = HistoryPCType::ReturnsNoZerothFrame;
}
ExpressionResults expr_result = UserExpression::Evaluate(
@@ -197,10 +205,10 @@ HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {
if (!return_value_sp)
return result;
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free",
- "Memory deallocated by", result);
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc",
- "Memory allocated by", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, pc_type,
+ "free", "Memory deallocated by", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, pc_type,
+ "alloc", "Memory allocated by", result);
return result;
}
diff --git a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
index 7d25ec3e21811..3b0618fa10374 100644
--- a/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
+++ b/lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -51,6 +51,17 @@ HistoryUnwind::DoCreateRegisterContextForFrame(StackFrame *frame) {
return rctx;
}
+static bool BehavesLikeZerothFrame(HistoryPCType pc_type, uint32_t frame_idx) {
+ switch (pc_type) {
+ case HistoryPCType::Returns:
+ return (frame_idx == 0);
+ case HistoryPCType::ReturnsNoZerothFrame:
+ return false;
+ case HistoryPCType::Calls:
+ return true;
+ }
+}
+
bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
lldb::addr_t &pc,
bool &behaves_like_zeroth_frame) {
@@ -60,10 +71,7 @@ bool HistoryUnwind::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
if (frame_idx < m_pcs.size()) {
cfa = frame_idx;
pc = m_pcs[frame_idx];
- if (m_pc_type == HistoryPCType::Calls)
- behaves_like_zeroth_frame = true;
- else
- behaves_like_zeroth_frame = (frame_idx == 0);
+ behaves_like_zeroth_frame = BehavesLikeZerothFrame(m_pc_type, frame_idx);
return true;
}
return false;
diff --git a/lldb/test/API/functionalities/asan/TestMemoryHistory.py b/lldb/test/API/functionalities/asan/TestMemoryHistory.py
index 1568140b355dc..66f6e3e7502c1 100644
--- a/lldb/test/API/functionalities/asan/TestMemoryHistory.py
+++ b/lldb/test/API/functionalities/asan/TestMemoryHistory.py
@@ -41,18 +41,16 @@ def setUp(self):
self.line_free = line_number("main.c", "// free line")
self.line_breakpoint = line_number("main.c", "// break line")
- # Test line numbers: rdar://126237493
- # for libsanitizers and remove `skip_line_numbers` parameter
- def check_traces(self, skip_line_numbers=False):
+ def check_traces(self):
self.expect(
"memory history 'pointer'",
substrs=[
"Memory deallocated by Thread",
"a.out`f2",
- "main.c" if skip_line_numbers else f"main.c:{self.line_free}",
+ f"main.c:{self.line_free}",
"Memory allocated by Thread",
"a.out`f1",
- "main.c" if skip_line_numbers else f"main.c:{self.line_malloc}",
+ f"main.c:{self.line_malloc}",
],
)
@@ -76,7 +74,7 @@ def libsanitizers_traces_tests(self):
self.runCmd("env SanitizersAllocationTraces=all")
self.run_to_breakpoint(target)
- self.check_traces(skip_line_numbers=True)
+ self.check_traces()
def libsanitizers_asan_tests(self):
target = self.createTestTarget()
@@ -84,7 +82,7 @@ def libsanitizers_asan_tests(self):
self.runCmd("env SanitizersAddress=1 MallocSanitizerZone=1")
self.run_to_breakpoint(target)
- self.check_traces(skip_line_numbers=True)
+ self.check_traces()
self.runCmd("continue")
@@ -94,7 +92,7 @@ def libsanitizers_asan_tests(self):
"Process should be stopped due to ASan report",
substrs=["stopped", "stop reason = Use of deallocated memory"],
)
- self.check_traces(skip_line_numbers=True)
+ self.check_traces()
# do the same using SB API
process = self.dbg.GetSelectedTarget().process
>From 32ec4650ae0999b69ea3a0e08186bce7c090bae9 Mon Sep 17 00:00:00 2001
From: Julian Lettner <jlettner at apple.com>
Date: Wed, 20 Aug 2025 11:36:31 -0700
Subject: [PATCH 3/3] [lldb] Refactor `GetPreferredAsanModule()` to also return
the `HistoryPCType`
---
.../Utility/ReportRetriever.cpp | 2 +-
.../Utility/Utility.cpp | 19 +++++++++++++++----
.../InstrumentationRuntime/Utility/Utility.h | 8 +++++---
.../MemoryHistory/asan/MemoryHistoryASan.cpp | 17 ++---------------
4 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
index 96489248022eb..38c334bfb78ac 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/ReportRetriever.cpp
@@ -83,7 +83,7 @@ ReportRetriever::RetrieveReportData(const ProcessSP process_sp) {
options.SetAutoApplyFixIts(false);
options.SetLanguage(eLanguageTypeObjC_plus_plus);
- if (auto m = GetPreferredAsanModule(process_sp->GetTarget())) {
+ if (auto [m, _] = GetPreferredAsanModule(process_sp->GetTarget()); m) {
SymbolContextList sc_list;
sc_list.Append(SymbolContext(std::move(m)));
options.SetPreferredSymbolContexts(std::move(sc_list));
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
index a5cee5d324325..09c6988b07050 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
@@ -13,10 +13,12 @@
namespace lldb_private {
-lldb::ModuleSP GetPreferredAsanModule(const Target &target) {
- // Currently only supported on Darwin.
+std::tuple<lldb::ModuleSP, HistoryPCType>
+GetPreferredAsanModule(const Target &target) {
+ // Currently only Darwin provides ASan runtime support as part of the OS
+ // (libsanitizers).
if (!target.GetArchitecture().GetTriple().isOSDarwin())
- return nullptr;
+ return {nullptr, HistoryPCType::Calls};
lldb::ModuleSP module;
llvm::Regex pattern(R"(libclang_rt\.asan_.*_dynamic\.dylib)");
@@ -29,7 +31,16 @@ lldb::ModuleSP GetPreferredAsanModule(const Target &target) {
return IterationAction::Continue;
});
- return module;
+ // `Calls` - The ASan compiler-rt runtime already massages the return
+ // addresses into call addresses, so we don't want LLDB's unwinder to try to
+ // locate the previous instruction again as this might lead to us reporting
+ // a different line.
+ // `ReturnsNoZerothFrame` - Darwin, but not ASan compiler-rt implies
+ // libsanitizers which collects return addresses. It also discards a few
+ // non-user frames at the top of the stack.
+ auto pc_type =
+ (module ? HistoryPCType::Calls : HistoryPCType::ReturnsNoZerothFrame);
+ return {module, pc_type};
}
} // namespace lldb_private
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h
index 425f0a2d35640..e26d2bc559e58 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.h
@@ -9,18 +9,20 @@
#ifndef LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H
#define LLDB_SOURCE_PLUGINS_INSTRUMENTATIONRUNTIME_UTILITY_UTILITY_H
+#include <tuple>
+
#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
namespace lldb_private {
-class Target;
-
/// On Darwin, if LLDB loaded libclang_rt, it's coming from a locally built
/// compiler-rt, and we should prefer it in favour of the system sanitizers
/// when running InstrumentationRuntime utility expressions that use symbols
/// from the sanitizer libraries. This helper searches the target for such a
/// dylib. Returns nullptr if no such dylib was found.
-lldb::ModuleSP GetPreferredAsanModule(const Target &target);
+std::tuple<lldb::ModuleSP, HistoryPCType>
+GetPreferredAsanModule(const Target &target);
} // namespace lldb_private
diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index ab8de10023e2d..206a47165f762 100644
--- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -170,24 +170,11 @@ HistoryThreads MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) {
options.SetAutoApplyFixIts(false);
options.SetLanguage(eLanguageTypeObjC_plus_plus);
- // The ASan compiler-rt runtime already massages the return addresses into
- // call addresses, so we don't want LLDB's unwinder to try to locate the
- // previous instruction again as this might lead to us reporting a different
- // line.
- auto pc_type = HistoryPCType::Calls;
-
- if (auto m = GetPreferredAsanModule(process_sp->GetTarget())) {
+ auto [m, pc_type] = GetPreferredAsanModule(process_sp->GetTarget());
+ if (m) {
SymbolContextList sc_list;
sc_list.Append(SymbolContext(std::move(m)));
options.SetPreferredSymbolContexts(std::move(sc_list));
- } else if (process_sp->GetTarget()
- .GetArchitecture()
- .GetTriple()
- .isOSDarwin()) {
- // Darwin, but not ASan compiler-rt implies libsanitizers which collects
- // return addresses. It also discards a few non-user frames at the top of
- // the stack.
- pc_type = HistoryPCType::ReturnsNoZerothFrame;
}
ExpressionResults expr_result = UserExpression::Evaluate(
More information about the lldb-commits
mailing list