https://github.com/labath updated 
https://github.com/llvm/llvm-project/pull/127661

>From 8419178c265d64ee07fe72089421f500f4bb5452 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pa...@labath.sk>
Date: Tue, 18 Feb 2025 16:14:30 +0100
Subject: [PATCH] [lldb] s/ValidRange/ValidRanges in UnwindPlan

To be able to describe discontinuous functions, this patch changes the
UnwindPlan to accept more than one address range.

I've also squeezed in a couple improvements/modernizations, for example
using the lower_bound function instead of a linear scan.
---
 lldb/include/lldb/Symbol/UnwindPlan.h         | 17 ++--
 .../ObjectFile/PECOFF/PECallFrameInfo.cpp     |  4 +-
 .../Breakpad/SymbolFileBreakpad.cpp           | 12 +--
 .../x86/x86AssemblyInspectionEngine.cpp       |  4 +-
 lldb/source/Symbol/CompactUnwindInfo.cpp      |  2 +-
 lldb/source/Symbol/DWARFCallFrameInfo.cpp     |  2 +-
 lldb/source/Symbol/UnwindPlan.cpp             | 90 ++++++++-----------
 lldb/unittests/Symbol/CMakeLists.txt          |  1 +
 lldb/unittests/Symbol/UnwindPlanTest.cpp      | 76 ++++++++++++++++
 .../x86/Testx86AssemblyInspectionEngine.cpp   |  6 +-
 10 files changed, 138 insertions(+), 76 deletions(-)
 create mode 100644 lldb/unittests/Symbol/UnwindPlanTest.cpp

diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h 
b/lldb/include/lldb/Symbol/UnwindPlan.h
index 462c1a52b01db..e4d34b8cf7773 100644
--- a/lldb/include/lldb/Symbol/UnwindPlan.h
+++ b/lldb/include/lldb/Symbol/UnwindPlan.h
@@ -438,7 +438,7 @@ class UnwindPlan {
 
   // Performs a deep copy of the plan, including all the rows (expensive).
   UnwindPlan(const UnwindPlan &rhs)
-      : m_plan_valid_address_range(rhs.m_plan_valid_address_range),
+      : m_plan_valid_ranges(rhs.m_plan_valid_ranges),
         m_register_kind(rhs.m_register_kind),
         m_return_addr_register(rhs.m_return_addr_register),
         m_source_name(rhs.m_source_name),
@@ -492,10 +492,8 @@ class UnwindPlan {
   // This UnwindPlan may not be valid at every address of the function span.
   // For instance, a FastUnwindPlan will not be valid at the prologue setup
   // instructions - only in the body of the function.
-  void SetPlanValidAddressRange(const AddressRange &range);
-
-  const AddressRange &GetAddressRange() const {
-    return m_plan_valid_address_range;
+  void SetPlanValidAddressRanges(std::vector<AddressRange> ranges) {
+    m_plan_valid_ranges = std::move(ranges);
   }
 
   bool PlanValidAtAddress(Address addr);
@@ -544,11 +542,11 @@ class UnwindPlan {
     m_plan_is_for_signal_trap = is_for_signal_trap;
   }
 
-  int GetRowCount() const;
+  int GetRowCount() const { return m_row_list.size(); }
 
   void Clear() {
     m_row_list.clear();
-    m_plan_valid_address_range.Clear();
+    m_plan_valid_ranges.clear();
     m_register_kind = lldb::eRegisterKindDWARF;
     m_source_name.Clear();
     m_plan_is_sourced_from_compiler = eLazyBoolCalculate;
@@ -571,9 +569,8 @@ class UnwindPlan {
   }
 
 private:
-  typedef std::vector<RowSP> collection;
-  collection m_row_list;
-  AddressRange m_plan_valid_address_range;
+  std::vector<RowSP> m_row_list;
+  std::vector<AddressRange> m_plan_valid_ranges;
   lldb::RegisterKind m_register_kind; // The RegisterKind these register 
numbers
                                       // are in terms of - will need to be
   // translated to lldb native reg nums at unwind time
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp 
b/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
index 9bd48f2b9f60f..abb9cbde35711 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/PECallFrameInfo.cpp
@@ -495,9 +495,9 @@ bool PECallFrameInfo::GetUnwindPlan(const AddressRange 
&range,
   for (auto it = rows.rbegin(); it != rows.rend(); ++it)
     unwind_plan.AppendRow(*it);
 
-  unwind_plan.SetPlanValidAddressRange(AddressRange(
+  unwind_plan.SetPlanValidAddressRanges({AddressRange(
       m_object_file.GetAddress(runtime_function->StartAddress),
-      runtime_function->EndAddress - runtime_function->StartAddress));
+      runtime_function->EndAddress - runtime_function->StartAddress)});
   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
 
   return true;
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp 
b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index dee5a7ce2876d..1e53f5f7b9a6f 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -656,9 +656,9 @@ SymbolFileBreakpad::ParseCFIUnwindPlan(const Bookmark 
&bookmark,
   plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
   plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
   plan_sp->SetSourcedFromCompiler(eLazyBoolYes);
-  plan_sp->SetPlanValidAddressRange(
-      AddressRange(base + init_record->Address, *init_record->Size,
-                   m_objfile_sp->GetModule()->GetSectionList()));
+  plan_sp->SetPlanValidAddressRanges(
+      {AddressRange(base + init_record->Address, *init_record->Size,
+                    m_objfile_sp->GetModule()->GetSectionList())});
 
   auto row_sp = std::make_shared<UnwindPlan::Row>();
   row_sp->SetOffset(0);
@@ -698,9 +698,9 @@ SymbolFileBreakpad::ParseWinUnwindPlan(const Bookmark 
&bookmark,
   plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
   plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
   plan_sp->SetSourcedFromCompiler(eLazyBoolYes);
-  plan_sp->SetPlanValidAddressRange(
-      AddressRange(base + record->RVA, record->CodeSize,
-                   m_objfile_sp->GetModule()->GetSectionList()));
+  plan_sp->SetPlanValidAddressRanges(
+      {AddressRange(base + record->RVA, record->CodeSize,
+                    m_objfile_sp->GetModule()->GetSectionList())});
 
   auto row_sp = std::make_shared<UnwindPlan::Row>();
   row_sp->SetOffset(0);
diff --git 
a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp 
b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 84f37ebe52492..90f40c9d1b55f 100644
--- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -918,7 +918,7 @@ bool 
x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
   UnwindPlan::Row::AbstractRegisterLocation initial_regloc;
   UnwindPlan::RowSP row(new UnwindPlan::Row);
 
-  unwind_plan.SetPlanValidAddressRange(func_range);
+  unwind_plan.SetPlanValidAddressRanges({func_range});
   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
 
   // At the start of the function, find the CFA by adding wordsize to the SP
@@ -1573,7 +1573,7 @@ bool 
x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
     }
   }
 
-  unwind_plan.SetPlanValidAddressRange(func_range);
+  unwind_plan.SetPlanValidAddressRanges({func_range});
   if (unwind_plan_updated) {
     std::string unwind_plan_source(unwind_plan.GetSourceName().AsCString());
     unwind_plan_source += " plus augmentation from assembly parsing";
diff --git a/lldb/source/Symbol/CompactUnwindInfo.cpp 
b/lldb/source/Symbol/CompactUnwindInfo.cpp
index c9039ea51ff70..fdce79e92ae13 100644
--- a/lldb/source/Symbol/CompactUnwindInfo.cpp
+++ b/lldb/source/Symbol/CompactUnwindInfo.cpp
@@ -206,7 +206,7 @@ bool CompactUnwindInfo::GetUnwindPlan(Target &target, 
Address addr,
                                   function_info.valid_range_offset_end -
                                       function_info.valid_range_offset_start,
                                   sl);
-          unwind_plan.SetPlanValidAddressRange(func_range);
+          unwind_plan.SetPlanValidAddressRanges({func_range});
         }
       }
 
diff --git a/lldb/source/Symbol/DWARFCallFrameInfo.cpp 
b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
index a743de596b8d8..19839c80659fe 100644
--- a/lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -623,7 +623,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t 
dwarf_offset,
   uint32_t code_align = cie->code_align;
   int32_t data_align = cie->data_align;
 
-  unwind_plan.SetPlanValidAddressRange(range);
+  unwind_plan.SetPlanValidAddressRanges({range});
   UnwindPlan::Row *cie_initial_row = new UnwindPlan::Row;
   *cie_initial_row = cie->initial_row;
   UnwindPlan::RowSP row(cie_initial_row);
diff --git a/lldb/source/Symbol/UnwindPlan.cpp 
b/lldb/source/Symbol/UnwindPlan.cpp
index a3df927cddae8..b9c55c3e0ce58 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -15,6 +15,7 @@
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include <optional>
@@ -397,36 +398,35 @@ void UnwindPlan::AppendRow(const UnwindPlan::RowSP 
&row_sp) {
     m_row_list.back() = row_sp;
 }
 
+struct RowLess {
+  bool operator()(addr_t a, const UnwindPlan::RowSP &b) const {
+    return a < b->GetOffset();
+  }
+  bool operator()(const UnwindPlan::RowSP &a, addr_t b) const {
+    return a->GetOffset() < b;
+  }
+};
+
 void UnwindPlan::InsertRow(const UnwindPlan::RowSP &row_sp,
                            bool replace_existing) {
-  collection::iterator it = m_row_list.begin();
-  while (it != m_row_list.end()) {
-    RowSP row = *it;
-    if (row->GetOffset() >= row_sp->GetOffset())
-      break;
-    it++;
-  }
-  if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset())
+  auto it = llvm::lower_bound(m_row_list, row_sp->GetOffset(), RowLess());
+  if (it == m_row_list.end() || it->get()->GetOffset() > row_sp->GetOffset())
     m_row_list.insert(it, row_sp);
-  else if (replace_existing)
-    *it = row_sp;
+  else {
+    assert(it->get()->GetOffset() == row_sp->GetOffset());
+    if (replace_existing)
+      *it = row_sp;
+  }
 }
 
 const UnwindPlan::Row *UnwindPlan::GetRowForFunctionOffset(int offset) const {
-  if (m_row_list.empty())
+  auto it = offset == -1 ? m_row_list.end()
+                         : llvm::upper_bound(m_row_list, offset, RowLess());
+  if (it == m_row_list.begin())
     return nullptr;
-  if (offset == -1)
-    return m_row_list.back().get();
-
-  RowSP row;
-  collection::const_iterator pos, end = m_row_list.end();
-  for (pos = m_row_list.begin(); pos != end; ++pos) {
-    if ((*pos)->GetOffset() <= static_cast<lldb::offset_t>(offset))
-      row = *pos;
-    else
-      break;
-  }
-  return row.get();
+  // upper_bound returns the row strictly greater than our desired offset, 
which
+  // means that the row before it is a match.
+  return std::prev(it)->get();
 }
 
 bool UnwindPlan::IsValidRowIndex(uint32_t idx) const {
@@ -445,20 +445,13 @@ const UnwindPlan::Row *UnwindPlan::GetRowAtIndex(uint32_t 
idx) const {
 
 const UnwindPlan::Row *UnwindPlan::GetLastRow() const {
   if (m_row_list.empty()) {
-    Log *log = GetLog(LLDBLog::Unwind);
-    LLDB_LOGF(log, "UnwindPlan::GetLastRow() when rows are empty");
+    LLDB_LOG(GetLog(LLDBLog::Unwind),
+             "UnwindPlan::GetLastRow() when rows are empty");
     return nullptr;
   }
   return m_row_list.back().get();
 }
 
-int UnwindPlan::GetRowCount() const { return m_row_list.size(); }
-
-void UnwindPlan::SetPlanValidAddressRange(const AddressRange &range) {
-  if (range.GetBaseAddress().IsValid() && range.GetByteSize() != 0)
-    m_plan_valid_address_range = range;
-}
-
 bool UnwindPlan::PlanValidAtAddress(Address addr) {
   // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
   if (GetRowCount() == 0) {
@@ -482,9 +475,9 @@ bool UnwindPlan::PlanValidAtAddress(Address addr) {
   // If the 0th Row of unwind instructions is missing, or if it doesn't provide
   // a register to use to find the Canonical Frame Address, this is not a valid
   // UnwindPlan.
-  if (GetRowAtIndex(0) == nullptr ||
-      GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
-          Row::FAValue::unspecified) {
+  const Row *row0 = GetRowForFunctionOffset(0);
+  if (!row0 ||
+      row0->GetCFAValue().GetValueType() == Row::FAValue::unspecified) {
     Log *log = GetLog(LLDBLog::Unwind);
     if (log) {
       StreamString s;
@@ -503,17 +496,15 @@ bool UnwindPlan::PlanValidAtAddress(Address addr) {
     return false;
   }
 
-  if (!m_plan_valid_address_range.GetBaseAddress().IsValid() ||
-      m_plan_valid_address_range.GetByteSize() == 0)
+  if (m_plan_valid_ranges.empty())
     return true;
 
   if (!addr.IsValid())
     return true;
 
-  if (m_plan_valid_address_range.ContainsFileAddress(addr))
-    return true;
-
-  return false;
+  return llvm::any_of(m_plan_valid_ranges, [&](const AddressRange &range) {
+    return range.ContainsFileAddress(addr);
+  });
 }
 
 void UnwindPlan::Dump(Stream &s, Thread *thread, lldb::addr_t base_addr) const 
{
@@ -570,20 +561,17 @@ void UnwindPlan::Dump(Stream &s, Thread *thread, 
lldb::addr_t base_addr) const {
     s.Printf("not specified.\n");
     break;
   }
-  if (m_plan_valid_address_range.GetBaseAddress().IsValid() &&
-      m_plan_valid_address_range.GetByteSize() > 0) {
+  if (!m_plan_valid_ranges.empty()) {
     s.PutCString("Address range of this UnwindPlan: ");
     TargetSP target_sp(thread->CalculateTarget());
-    m_plan_valid_address_range.Dump(&s, target_sp.get(),
-                                    Address::DumpStyleSectionNameOffset);
+    for (const AddressRange &range : m_plan_valid_ranges)
+      range.Dump(&s, target_sp.get(), Address::DumpStyleSectionNameOffset);
     s.EOL();
   }
-  collection::const_iterator pos, begin = m_row_list.begin(),
-                                  end = m_row_list.end();
-  for (pos = begin; pos != end; ++pos) {
-    s.Printf("row[%u]: ", (uint32_t)std::distance(begin, pos));
-    (*pos)->Dump(s, this, thread, base_addr);
-    s.Printf("\n");
+  for (const auto &[index, row_sp] : llvm::enumerate(m_row_list)) {
+    s.Format("row[{0}]: ", index);
+    row_sp->Dump(s, this, thread, base_addr);
+    s << "\n";
   }
 }
 
diff --git a/lldb/unittests/Symbol/CMakeLists.txt 
b/lldb/unittests/Symbol/CMakeLists.txt
index ab5cecd101833..5664c21adbe3f 100644
--- a/lldb/unittests/Symbol/CMakeLists.txt
+++ b/lldb/unittests/Symbol/CMakeLists.txt
@@ -12,6 +12,7 @@ add_lldb_unittest(SymbolTests
   TestDWARFCallFrameInfo.cpp
   TestType.cpp
   TestLineEntry.cpp
+  UnwindPlanTest.cpp
 
   LINK_LIBS
     lldbCore
diff --git a/lldb/unittests/Symbol/UnwindPlanTest.cpp 
b/lldb/unittests/Symbol/UnwindPlanTest.cpp
new file mode 100644
index 0000000000000..afbd9ab6ac38d
--- /dev/null
+++ b/lldb/unittests/Symbol/UnwindPlanTest.cpp
@@ -0,0 +1,76 @@
+//===-- UnwindPlanTest.cpp 
------------------------------------------------===//
+//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/UnwindPlan.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+static UnwindPlan::RowSP make_simple_row(addr_t offset, uint64_t cfa_value) {
+  UnwindPlan::RowSP row_sp = std::make_shared<UnwindPlan::Row>();
+  row_sp->SetOffset(offset);
+  row_sp->GetCFAValue().SetIsConstant(cfa_value);
+  return row_sp;
+}
+
+TEST(UnwindPlan, InsertRow) {
+  UnwindPlan::RowSP row1_sp = make_simple_row(0, 42);
+  UnwindPlan::RowSP row2_sp = make_simple_row(0, 47);
+
+  UnwindPlan plan(eRegisterKindGeneric);
+  plan.InsertRow(row1_sp);
+  EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(*row1_sp));
+
+  plan.InsertRow(row2_sp, /*replace_existing=*/false);
+  EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(*row1_sp));
+
+  plan.InsertRow(row2_sp, /*replace_existing=*/true);
+  EXPECT_THAT(plan.GetRowForFunctionOffset(0), testing::Pointee(*row2_sp));
+}
+
+TEST(UnwindPlan, GetRowForFunctionOffset) {
+  UnwindPlan::RowSP row1_sp = make_simple_row(10, 42);
+  UnwindPlan::RowSP row2_sp = make_simple_row(20, 47);
+
+  UnwindPlan plan(eRegisterKindGeneric);
+  plan.InsertRow(row1_sp);
+  plan.InsertRow(row2_sp);
+
+  EXPECT_THAT(plan.GetRowForFunctionOffset(0), nullptr);
+  EXPECT_THAT(plan.GetRowForFunctionOffset(9), nullptr);
+  EXPECT_THAT(plan.GetRowForFunctionOffset(10), testing::Pointee(*row1_sp));
+  EXPECT_THAT(plan.GetRowForFunctionOffset(19), testing::Pointee(*row1_sp));
+  EXPECT_THAT(plan.GetRowForFunctionOffset(20), testing::Pointee(*row2_sp));
+  EXPECT_THAT(plan.GetRowForFunctionOffset(99), testing::Pointee(*row2_sp));
+}
+
+TEST(UnwindPlan, PlanValidAtAddress) {
+  UnwindPlan::RowSP row1_sp = make_simple_row(0, 42);
+  UnwindPlan::RowSP row2_sp = make_simple_row(10, 47);
+
+  UnwindPlan plan(eRegisterKindGeneric);
+  EXPECT_FALSE(plan.PlanValidAtAddress(Address(0)));
+
+  plan.InsertRow(row2_sp);
+  EXPECT_FALSE(plan.PlanValidAtAddress(Address(0)));
+
+  plan.InsertRow(row1_sp);
+  EXPECT_TRUE(plan.PlanValidAtAddress(Address(0)));
+  EXPECT_TRUE(plan.PlanValidAtAddress(Address(10)));
+
+  plan.SetPlanValidAddressRanges({AddressRange(0, 5), AddressRange(15, 5)});
+  EXPECT_TRUE(plan.PlanValidAtAddress(Address(0)));
+  EXPECT_FALSE(plan.PlanValidAtAddress(Address(5)));
+  EXPECT_FALSE(plan.PlanValidAtAddress(Address(10)));
+  EXPECT_TRUE(plan.PlanValidAtAddress(Address(15)));
+  EXPECT_FALSE(plan.PlanValidAtAddress(Address(20)));
+  EXPECT_FALSE(plan.PlanValidAtAddress(Address(25)));
+}
diff --git 
a/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp 
b/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
index 3600360fad229..c55e13fce6935 100644
--- a/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
+++ b/lldb/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
@@ -2248,7 +2248,7 @@ TEST_F(Testx86AssemblyInspectionEngine, 
TestSpArithx86_64Augmented) {
   sample_range = AddressRange(0x1000, sizeof(data));
 
   unwind_plan.SetSourceName("unit testing hand-created unwind plan");
-  unwind_plan.SetPlanValidAddressRange(sample_range);
+  unwind_plan.SetPlanValidAddressRanges({sample_range});
   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
 
   row_sp = std::make_shared<UnwindPlan::Row>();
@@ -2335,7 +2335,7 @@ TEST_F(Testx86AssemblyInspectionEngine, 
TestSimplex86_64Augmented) {
   sample_range = AddressRange(0x1000, sizeof(data));
 
   unwind_plan.SetSourceName("unit testing hand-created unwind plan");
-  unwind_plan.SetPlanValidAddressRange(sample_range);
+  unwind_plan.SetPlanValidAddressRanges({sample_range});
   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
 
   row_sp = std::make_shared<UnwindPlan::Row>();
@@ -2413,7 +2413,7 @@ TEST_F(Testx86AssemblyInspectionEngine, 
TestSimplei386ugmented) {
   sample_range = AddressRange(0x1000, sizeof(data));
 
   unwind_plan.SetSourceName("unit testing hand-created unwind plan");
-  unwind_plan.SetPlanValidAddressRange(sample_range);
+  unwind_plan.SetPlanValidAddressRanges({sample_range});
   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
 
   row_sp = std::make_shared<UnwindPlan::Row>();

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to