https://github.com/mbucko created 
https://github.com/llvm/llvm-project/pull/92014

Summary:
This adds new SB API calls and classes to allow a user of the SB API to obtain 
an address range from SBFunction and SBBlock.

Test Plan:

Reviewers: clayborg

Subscribers: lldb-commits

Tasks:

Tags:

>From 309050cf7cecab87b851e5d70f5f7437577a828f Mon Sep 17 00:00:00 2001
From: Miro Bucko <mbu...@meta.com>
Date: Fri, 10 May 2024 12:42:03 -0700
Subject: [PATCH] Add AddressRange to SB API

Summary:
This adds new SB API calls and classes to allow a user of the SB API to
obtain an address range from SBFunction and SBBlock.

Test Plan:

Reviewers: clayborg

Subscribers: lldb-commits

Tasks:

Tags:
---
 lldb/bindings/headers.swig                    |   2 +
 .../interface/SBAddressRangeDocstrings.i      |   3 +
 .../interface/SBAddressRangeListDocstrings.i  |   3 +
 .../interface/SBAddressRangeListExtensions.i  |  13 ++
 lldb/bindings/interfaces.swig                 |   2 +
 lldb/include/lldb/API/LLDB.h                  |   2 +
 lldb/include/lldb/API/SBAddress.h             |   1 +
 lldb/include/lldb/API/SBAddressRange.h        |  63 +++++++++
 lldb/include/lldb/API/SBAddressRangeList.h    |  57 ++++++++
 lldb/include/lldb/API/SBBlock.h               |   3 +
 lldb/include/lldb/API/SBDefines.h             |   2 +
 lldb/include/lldb/API/SBFunction.h            |   3 +
 lldb/include/lldb/Core/AddressRange.h         |   8 ++
 lldb/include/lldb/lldb-forward.h              |   3 +
 lldb/source/API/CMakeLists.txt                |   2 +
 lldb/source/API/SBAddressRange.cpp            |  78 +++++++++++
 lldb/source/API/SBAddressRangeList.cpp        | 131 ++++++++++++++++++
 lldb/source/API/SBBlock.cpp                   |  10 ++
 lldb/source/API/SBFunction.cpp                |  11 ++
 lldb/source/Core/AddressRange.cpp             |   4 +
 .../API/python_api/address_range/Makefile     |   3 +
 .../address_range/TestAddressRange.py         | 124 +++++++++++++++++
 .../API/python_api/address_range/main.cpp     |   5 +
 23 files changed, 533 insertions(+)
 create mode 100644 lldb/bindings/interface/SBAddressRangeDocstrings.i
 create mode 100644 lldb/bindings/interface/SBAddressRangeListDocstrings.i
 create mode 100644 lldb/bindings/interface/SBAddressRangeListExtensions.i
 create mode 100644 lldb/include/lldb/API/SBAddressRange.h
 create mode 100644 lldb/include/lldb/API/SBAddressRangeList.h
 create mode 100644 lldb/source/API/SBAddressRange.cpp
 create mode 100644 lldb/source/API/SBAddressRangeList.cpp
 create mode 100644 lldb/test/API/python_api/address_range/Makefile
 create mode 100644 lldb/test/API/python_api/address_range/TestAddressRange.py
 create mode 100644 lldb/test/API/python_api/address_range/main.cpp

diff --git a/lldb/bindings/headers.swig b/lldb/bindings/headers.swig
index e8d0cda288141..2b53eefc8568b 100644
--- a/lldb/bindings/headers.swig
+++ b/lldb/bindings/headers.swig
@@ -8,6 +8,8 @@
 %{
 #include "lldb/lldb-public.h"
 #include "lldb/API/SBAddress.h"
+#include "lldb/API/SBAddressRange.h"
+#include "lldb/API/SBAddressRangeList.h"
 #include "lldb/API/SBAttachInfo.h"
 #include "lldb/API/SBBlock.h"
 #include "lldb/API/SBBreakpoint.h"
diff --git a/lldb/bindings/interface/SBAddressRangeDocstrings.i 
b/lldb/bindings/interface/SBAddressRangeDocstrings.i
new file mode 100644
index 0000000000000..650195704d73e
--- /dev/null
+++ b/lldb/bindings/interface/SBAddressRangeDocstrings.i
@@ -0,0 +1,3 @@
+%feature("docstring",
+"API clients can get address range information."
+) lldb::SBAddressRange;
diff --git a/lldb/bindings/interface/SBAddressRangeListDocstrings.i 
b/lldb/bindings/interface/SBAddressRangeListDocstrings.i
new file mode 100644
index 0000000000000..e4b96b9ca5931
--- /dev/null
+++ b/lldb/bindings/interface/SBAddressRangeListDocstrings.i
@@ -0,0 +1,3 @@
+%feature("docstring",
+"Represents a list of :py:class:`SBAddressRange`."
+) lldb::SBAddressRangeList;
diff --git a/lldb/bindings/interface/SBAddressRangeListExtensions.i 
b/lldb/bindings/interface/SBAddressRangeListExtensions.i
new file mode 100644
index 0000000000000..781780b15e877
--- /dev/null
+++ b/lldb/bindings/interface/SBAddressRangeListExtensions.i
@@ -0,0 +1,13 @@
+%extend lldb::SBAddressRangeList {
+#ifdef SWIGPYTHON
+    %pythoncode%{
+    def __len__(self):
+      '''Return the number of address ranges in a lldb.SBAddressRangeList 
object.'''
+      return self.GetSize()
+
+    def __iter__(self):
+      '''Iterate over all the address ranges in a lldb.SBAddressRangeList 
object.'''
+      return lldb_iter(self, 'GetSize', 'GetAddressRangeAtIndex')
+    %}
+#endif
+}
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index a31a0b4af1eb6..b9aae318d0684 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -86,6 +86,8 @@
 
 /* API headers */
 %include "lldb/API/SBAddress.h"
+%include "lldb/API/SBAddressRange.h"
+%include "lldb/API/SBAddressRangeList.h"
 %include "lldb/API/SBAttachInfo.h"
 %include "lldb/API/SBBlock.h"
 %include "lldb/API/SBBreakpoint.h"
diff --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h
index b256544326a22..d8cc9f5067fe9 100644
--- a/lldb/include/lldb/API/LLDB.h
+++ b/lldb/include/lldb/API/LLDB.h
@@ -10,6 +10,8 @@
 #define LLDB_API_LLDB_H
 
 #include "lldb/API/SBAddress.h"
+#include "lldb/API/SBAddressRange.h"
+#include "lldb/API/SBAddressRangeList.h"
 #include "lldb/API/SBAttachInfo.h"
 #include "lldb/API/SBBlock.h"
 #include "lldb/API/SBBreakpoint.h"
diff --git a/lldb/include/lldb/API/SBAddress.h 
b/lldb/include/lldb/API/SBAddress.h
index 5e5f355ccc390..430dad4862dbf 100644
--- a/lldb/include/lldb/API/SBAddress.h
+++ b/lldb/include/lldb/API/SBAddress.h
@@ -86,6 +86,7 @@ class LLDB_API SBAddress {
   lldb::SBLineEntry GetLineEntry();
 
 protected:
+  friend class SBAddressRange;
   friend class SBBlock;
   friend class SBBreakpoint;
   friend class SBBreakpointLocation;
diff --git a/lldb/include/lldb/API/SBAddressRange.h 
b/lldb/include/lldb/API/SBAddressRange.h
new file mode 100644
index 0000000000000..2ff5b29593e58
--- /dev/null
+++ b/lldb/include/lldb/API/SBAddressRange.h
@@ -0,0 +1,63 @@
+//===-- SBAddressRange.h ----------------------------------------*- C++ 
-*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_API_SBADDRESSRANGE_H
+#define LLDB_API_SBADDRESSRANGE_H
+
+#include "lldb/API/SBDefines.h"
+
+namespace lldb {
+
+class LLDB_API SBAddressRange {
+public:
+  SBAddressRange();
+
+  SBAddressRange(const lldb::SBAddressRange &rhs);
+
+  SBAddressRange(lldb::addr_t file_addr, lldb::addr_t byte_size);
+
+  ~SBAddressRange();
+
+  const lldb::SBAddressRange &operator=(const lldb::SBAddressRange &rhs);
+
+  void Clear();
+
+  bool IsValid() const;
+
+  /// Get the base address of the range.
+  ///
+  /// \return
+  ///     Base address object.
+  lldb::SBAddress GetBaseAddress() const;
+
+  /// Get the byte size of this range.
+  ///
+  /// \return
+  ///     The size in bytes of this address range.
+  lldb::addr_t GetByteSize() const;
+
+protected:
+  friend class SBAddressRangeList;
+  friend class SBBlock;
+  friend class SBFunction;
+
+  lldb_private::AddressRange &ref();
+
+  const lldb_private::AddressRange &ref() const;
+
+private:
+  AddressRangeUP m_opaque_up;
+};
+
+#ifndef SWIG
+bool LLDB_API operator==(const SBAddressRange &lhs, const SBAddressRange &rhs);
+#endif
+
+} // namespace lldb
+
+#endif // LLDB_API_SBADDRESSRANGE_H
diff --git a/lldb/include/lldb/API/SBAddressRangeList.h 
b/lldb/include/lldb/API/SBAddressRangeList.h
new file mode 100644
index 0000000000000..81dab4a88d189
--- /dev/null
+++ b/lldb/include/lldb/API/SBAddressRangeList.h
@@ -0,0 +1,57 @@
+//===-- SBAddressRangeList.h ------------------------------------*- C++ 
-*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_API_SBADDRESSRANGELIST_H
+#define LLDB_API_SBADDRESSRANGELIST_H
+
+#include <memory>
+
+#include "lldb/API/SBDefines.h"
+
+class AddressRangeListImpl;
+
+namespace lldb {
+
+class LLDB_API SBAddressRangeList {
+public:
+  SBAddressRangeList();
+
+  SBAddressRangeList(const lldb::SBAddressRangeList &rhs);
+
+  ~SBAddressRangeList();
+
+  const lldb::SBAddressRangeList &operator=(const lldb::SBAddressRangeList 
&rhs);
+
+  uint32_t GetSize() const;
+
+  void Clear();
+
+  bool GetAddressRangeAtIndex(uint64_t idx, SBAddressRange &addr_range);
+
+  void Append(const lldb::SBAddressRange &addr_range);
+
+  void Append(const lldb::SBAddressRangeList &addr_range_list);
+
+protected:
+  const AddressRangeListImpl *operator->() const;
+
+  const AddressRangeListImpl &operator*() const;
+  
+private:
+  friend class SBProcess;
+
+  lldb_private::AddressRanges &ref();
+
+  const lldb_private::AddressRanges &ref() const;
+
+  std::unique_ptr<AddressRangeListImpl> m_opaque_up;
+};
+
+} // namespace lldb
+
+#endif // LLDB_API_SBADDRESSRANGELIST_H
diff --git a/lldb/include/lldb/API/SBBlock.h b/lldb/include/lldb/API/SBBlock.h
index 2570099f7652f..1071fe1ad0802 100644
--- a/lldb/include/lldb/API/SBBlock.h
+++ b/lldb/include/lldb/API/SBBlock.h
@@ -9,6 +9,7 @@
 #ifndef LLDB_API_SBBLOCK_H
 #define LLDB_API_SBBLOCK_H
 
+#include "lldb/API/SBAddressRange.h"
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBFrame.h"
 #include "lldb/API/SBTarget.h"
@@ -52,6 +53,8 @@ class LLDB_API SBBlock {
 
   lldb::SBAddress GetRangeEndAddress(uint32_t idx);
 
+  lldb::SBAddressRange GetRangeAtIndex(uint32_t idx);
+
   uint32_t GetRangeIndexForBlockAddress(lldb::SBAddress block_addr);
 
   lldb::SBValueList GetVariables(lldb::SBFrame &frame, bool arguments,
diff --git a/lldb/include/lldb/API/SBDefines.h 
b/lldb/include/lldb/API/SBDefines.h
index 1181920677b46..87c0a1c3661ca 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -43,6 +43,8 @@
 namespace lldb {
 
 class LLDB_API SBAddress;
+class LLDB_API SBAddressRange;
+class LLDB_API SBAddressRangeList;
 class LLDB_API SBAttachInfo;
 class LLDB_API SBBlock;
 class LLDB_API SBBreakpoint;
diff --git a/lldb/include/lldb/API/SBFunction.h 
b/lldb/include/lldb/API/SBFunction.h
index 71b372a818e4b..0e1f8b1cd15a0 100644
--- a/lldb/include/lldb/API/SBFunction.h
+++ b/lldb/include/lldb/API/SBFunction.h
@@ -10,6 +10,7 @@
 #define LLDB_API_SBFUNCTION_H
 
 #include "lldb/API/SBAddress.h"
+#include "lldb/API/SBAddressRange.h"
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBInstructionList.h"
 
@@ -44,6 +45,8 @@ class LLDB_API SBFunction {
 
   lldb::SBAddress GetEndAddress();
 
+  lldb::SBAddressRange GetRange();
+
   const char *GetArgumentName(uint32_t arg_idx);
 
   uint32_t GetPrologueByteSize();
diff --git a/lldb/include/lldb/Core/AddressRange.h 
b/lldb/include/lldb/Core/AddressRange.h
index 4a33c2d795876..503d6e862f831 100644
--- a/lldb/include/lldb/Core/AddressRange.h
+++ b/lldb/include/lldb/Core/AddressRange.h
@@ -86,6 +86,8 @@ class AddressRange {
   /// (LLDB_INVALID_ADDRESS) and a zero byte size.
   void Clear();
 
+  bool IsValid() const;
+
   /// Check if a section offset address is contained in this range.
   ///
   /// \param[in] so_addr
@@ -242,6 +244,12 @@ class AddressRange {
   lldb::addr_t m_byte_size = 0; ///< The size in bytes of this address range.
 };
 
+// Forward-declarable wrapper.
+class AddressRanges : public std::vector<lldb_private::AddressRange> {
+public:
+  using std::vector<lldb_private::AddressRange>::vector;
+};
+
 } // namespace lldb_private
 
 #endif // LLDB_CORE_ADDRESSRANGE_H
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 10ba921b9dac8..6d880b4da03c9 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -19,6 +19,8 @@ class ASTResultSynthesizer;
 class ASTStructExtractor;
 class Address;
 class AddressRange;
+class AddressRanges;
+class AddressRangeList;
 class AddressResolver;
 class ArchSpec;
 class Architecture;
@@ -308,6 +310,7 @@ template <unsigned N> class StreamBuffer;
 namespace lldb {
 
 typedef std::shared_ptr<lldb_private::ABI> ABISP;
+typedef std::unique_ptr<lldb_private::AddressRange> AddressRangeUP;
 typedef std::shared_ptr<lldb_private::Baton> BatonSP;
 typedef std::shared_ptr<lldb_private::Block> BlockSP;
 typedef std::shared_ptr<lldb_private::Breakpoint> BreakpointSP;
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index aa31caddfde3a..ce53dc6c635b4 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -38,6 +38,8 @@ add_custom_target(lldb-sbapi-dwarf-enums
 
 add_lldb_library(liblldb SHARED ${option_framework}
   SBAddress.cpp
+  SBAddressRange.cpp
+  SBAddressRangeList.cpp
   SBAttachInfo.cpp
   SBBlock.cpp
   SBBreakpoint.cpp
diff --git a/lldb/source/API/SBAddressRange.cpp 
b/lldb/source/API/SBAddressRange.cpp
new file mode 100644
index 0000000000000..8fce0efb3e3be
--- /dev/null
+++ b/lldb/source/API/SBAddressRange.cpp
@@ -0,0 +1,78 @@
+//===-- SBAddressRange.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/API/SBAddressRange.h"
+#include "lldb/API/SBAddress.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Utility/Instrumentation.h"
+#include "Utils.h"
+#include <cstddef>
+#include <memory>
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBAddressRange::SBAddressRange()
+    : m_opaque_up(std::make_unique<AddressRange>()) {
+  LLDB_INSTRUMENT_VA(this);
+}
+
+SBAddressRange::SBAddressRange(const SBAddressRange &rhs) {
+  LLDB_INSTRUMENT_VA(this, rhs);
+
+  m_opaque_up = clone(rhs.m_opaque_up);
+}
+
+SBAddressRange::SBAddressRange(lldb::addr_t file_addr, lldb::addr_t byte_size)
+  : m_opaque_up(std::make_unique<AddressRange>(file_addr, byte_size)) {
+  LLDB_INSTRUMENT_VA(this, file_addr, byte_size);
+}
+
+SBAddressRange::~SBAddressRange() = default;
+
+const SBAddressRange &SBAddressRange::operator=(const SBAddressRange &rhs) {
+  LLDB_INSTRUMENT_VA(this, rhs);
+
+  if (this != &rhs)
+    m_opaque_up = clone(rhs.m_opaque_up);
+  return *this;
+}
+
+void SBAddressRange::Clear() {
+  LLDB_INSTRUMENT_VA(this);
+
+  m_opaque_up.reset();
+}
+
+bool SBAddressRange::IsValid() const {
+  return m_opaque_up && m_opaque_up->IsValid();
+}
+
+lldb::SBAddress SBAddressRange::GetBaseAddress() const {
+  LLDB_INSTRUMENT_VA(this);
+
+  assert(m_opaque_up.get() && "AddressRange is NULL");
+  return lldb::SBAddress(m_opaque_up->GetBaseAddress());
+}
+
+lldb::addr_t SBAddressRange::GetByteSize() const {
+  LLDB_INSTRUMENT_VA(this);
+
+  assert(m_opaque_up.get() && "AddressRange is NULL");
+  return m_opaque_up->GetByteSize();
+}
+
+AddressRange &SBAddressRange::ref() {
+  assert(m_opaque_up.get() && "AddressRange is NULL");
+  return *m_opaque_up;
+}
+
+const AddressRange &SBAddressRange::ref() const {
+  assert(m_opaque_up.get() && "AddressRange is NULL");
+  return *m_opaque_up;
+}
diff --git a/lldb/source/API/SBAddressRangeList.cpp 
b/lldb/source/API/SBAddressRangeList.cpp
new file mode 100644
index 0000000000000..6226c4659a0a6
--- /dev/null
+++ b/lldb/source/API/SBAddressRangeList.cpp
@@ -0,0 +1,131 @@
+
+//===-- SBAddressRangeList.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/API/SBAddressRangeList.h"
+#include "lldb/API/SBAddressRange.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Utility/Instrumentation.h"
+#include "Utils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class AddressRangeListImpl {
+public:
+  AddressRangeListImpl() : m_ranges() {}
+
+  AddressRangeListImpl(const AddressRangeListImpl &rhs) = default;
+
+  AddressRangeListImpl &operator=(const AddressRangeListImpl &rhs) {
+    if (this == &rhs)
+      return *this;
+    m_ranges = rhs.m_ranges;
+    return *this;
+  }
+
+  size_t GetSize() const { return m_ranges.size(); }
+
+  void Reserve(size_t capacity) { return m_ranges.reserve(capacity); }
+
+  void Append(const AddressRange &sb_region) {
+    m_ranges.emplace_back(sb_region);
+  }
+
+  void Append(const AddressRangeListImpl &list) {
+    Reserve(GetSize() + list.GetSize());
+
+    for (const auto &range : list.m_ranges)
+      Append(range);
+  }
+
+  void Clear() { m_ranges.clear(); }
+
+  bool GetAddressRangeAtIndex(size_t index, AddressRange &addr_range) {
+    if (index >= GetSize())
+      return false;
+    addr_range = m_ranges[index];
+    return true;
+  }
+
+  AddressRanges &Ref() { return m_ranges; }
+
+  const AddressRanges &Ref() const { return m_ranges; }
+
+private:
+  AddressRanges m_ranges;
+};
+
+AddressRanges &SBAddressRangeList::ref() { return m_opaque_up->Ref(); }
+
+const AddressRanges &SBAddressRangeList::ref() const {
+  return m_opaque_up->Ref();
+}
+
+SBAddressRangeList::SBAddressRangeList()
+    : m_opaque_up(new AddressRangeListImpl()) {
+  LLDB_INSTRUMENT_VA(this);
+}
+
+SBAddressRangeList::SBAddressRangeList(
+    const SBAddressRangeList &rhs)
+    : m_opaque_up(new AddressRangeListImpl(*rhs.m_opaque_up)) {
+  LLDB_INSTRUMENT_VA(this, rhs);
+}
+
+SBAddressRangeList::~SBAddressRangeList() = default;
+
+const SBAddressRangeList &SBAddressRangeList::
+operator=(const SBAddressRangeList &rhs) {
+  LLDB_INSTRUMENT_VA(this, rhs);
+
+  if (this != &rhs) {
+    *m_opaque_up = *rhs.m_opaque_up;
+  }
+  return *this;
+}
+
+uint32_t SBAddressRangeList::GetSize() const {
+  LLDB_INSTRUMENT_VA(this);
+
+  return m_opaque_up->GetSize();
+}
+
+bool SBAddressRangeList::GetAddressRangeAtIndex(
+    uint64_t idx, SBAddressRange &addr_range) {
+  LLDB_INSTRUMENT_VA(this, idx, addr_range);
+
+  return m_opaque_up->GetAddressRangeAtIndex(idx, addr_range.ref());
+}
+
+void SBAddressRangeList::Clear() {
+  LLDB_INSTRUMENT_VA(this);
+
+  m_opaque_up->Clear();
+}
+
+void SBAddressRangeList::Append(const SBAddressRange &sb_addr_range) {
+  LLDB_INSTRUMENT_VA(this, sb_addr_range);
+
+  m_opaque_up->Append(sb_addr_range.ref());
+}
+
+void SBAddressRangeList::Append(const SBAddressRangeList &sb_addr_range_list) {
+  LLDB_INSTRUMENT_VA(this, sb_addr_range_list);
+
+  m_opaque_up->Append(*sb_addr_range_list);
+}
+
+const AddressRangeListImpl *SBAddressRangeList::operator->() const {
+  return m_opaque_up.get();
+}
+
+const AddressRangeListImpl &SBAddressRangeList::operator*() const {
+  assert(m_opaque_up.get());
+  return *m_opaque_up;
+}
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index 7d7565340836b..0726777ddd6e9 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -219,6 +219,16 @@ lldb::SBAddress SBBlock::GetRangeEndAddress(uint32_t idx) {
   return sb_addr;
 }
 
+lldb::SBAddressRange SBBlock::GetRangeAtIndex(uint32_t idx) {
+  LLDB_INSTRUMENT_VA(this, idx);
+
+  lldb::SBAddressRange sb_range;
+  if (m_opaque_ptr) {
+    m_opaque_ptr->GetRangeAtIndex(idx, sb_range.ref());
+  }
+  return sb_range;
+}
+
 uint32_t SBBlock::GetRangeIndexForBlockAddress(lldb::SBAddress block_addr) {
   LLDB_INSTRUMENT_VA(this, block_addr);
 
diff --git a/lldb/source/API/SBFunction.cpp b/lldb/source/API/SBFunction.cpp
index a01c7f79bbd31..4f916357370d3 100644
--- a/lldb/source/API/SBFunction.cpp
+++ b/lldb/source/API/SBFunction.cpp
@@ -160,6 +160,17 @@ SBAddress SBFunction::GetEndAddress() {
   return addr;
 }
 
+lldb::SBAddressRange SBFunction::GetRange() {
+  LLDB_INSTRUMENT_VA(this);
+  
+  lldb::SBAddressRange range;
+  if (m_opaque_ptr) {
+    range.ref() = m_opaque_ptr->GetAddressRange();
+  }
+
+  return range;
+}
+
 const char *SBFunction::GetArgumentName(uint32_t arg_idx) {
   LLDB_INSTRUMENT_VA(this, arg_idx);
 
diff --git a/lldb/source/Core/AddressRange.cpp 
b/lldb/source/Core/AddressRange.cpp
index 1830f2ccd47fe..e9fa1b8f72b53 100644
--- a/lldb/source/Core/AddressRange.cpp
+++ b/lldb/source/Core/AddressRange.cpp
@@ -145,6 +145,10 @@ void AddressRange::Clear() {
   m_byte_size = 0;
 }
 
+bool AddressRange::IsValid() const {
+  return m_base_addr.IsValid() && (m_byte_size > 0);
+}
+
 bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style,
                         Address::DumpStyle fallback_style) const {
   addr_t vmaddr = LLDB_INVALID_ADDRESS;
diff --git a/lldb/test/API/python_api/address_range/Makefile 
b/lldb/test/API/python_api/address_range/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/python_api/address_range/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/address_range/TestAddressRange.py 
b/lldb/test/API/python_api/address_range/TestAddressRange.py
new file mode 100644
index 0000000000000..3f5e79a6ad1de
--- /dev/null
+++ b/lldb/test/API/python_api/address_range/TestAddressRange.py
@@ -0,0 +1,124 @@
+"""
+Test SBAddressRange APIs.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+
+
+class AddressRangeTestCase(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test_address_range_default(self):
+        """Testing default constructor."""
+        empty_range = lldb.SBAddressRange()
+        self.assertEqual(empty_range.IsValid(), False)
+
+    def test_address_range_construction(self):
+        """Make sure the construction and getters work."""
+        range = lldb.SBAddressRange(0x00000400, 8)
+        self.assertEqual(range.IsValid(), True)
+        self.assertEqual(range.GetBaseAddress().GetOffset(), 0x00000400)
+        self.assertEqual(range.GetByteSize(), 8)
+
+    def test_address_range_clear(self):
+        """Make sure the clear method works."""
+        range = lldb.SBAddressRange(0x00000400, 8)
+        self.assertEqual(range.IsValid(), True)
+        self.assertEqual(range.GetBaseAddress().GetOffset(), 0x00000400)
+        self.assertEqual(range.GetByteSize(), 8)
+
+        range.Clear()
+        self.assertEqual(range.IsValid(), False)
+
+    def test_function(self):
+        """Make sure the range works in SBFunction APIs."""
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+
+        # Create a target by the debugger.
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        # Setup breakpoints in main
+        bp = target.BreakpointCreateByName("main", "a.out")
+        loc = bp.GetLocationAtIndex(0)
+        loc_addr = loc.GetAddress()
+        func = loc_addr.GetFunction()
+        # block = loc_addr.GetBlock()
+        range = func.GetRange()
+        # block_ranges = block.GetRangeAtIndex(0)
+        self.assertEqual(
+            range.GetByteSize(),
+            func.GetEndAddress().GetOffset() - 
func.GetStartAddress().GetOffset(),
+        )
+        self.assertEqual(
+            range.GetBaseAddress().GetOffset(),
+            func.GetStartAddress().GetOffset(),
+        )
+
+    def test_block(self):
+        """Make sure the range works in SBBlock APIs."""
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+
+        # Create a target by the debugger.
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        # Setup breakpoints in main
+        bp = target.BreakpointCreateByName("main", "a.out")
+        loc = bp.GetLocationAtIndex(0)
+        loc_addr = loc.GetAddress()
+        block = loc_addr.GetBlock()
+        range = block.GetRangeAtIndex(0)
+        self.assertEqual(
+            range.GetByteSize(),
+            block.GetRangeEndAddress(0).GetOffset()
+            - block.GetRangeStartAddress(0).GetOffset(),
+        )
+        self.assertEqual(
+            range.GetBaseAddress().GetOffset(),
+            block.GetRangeStartAddress(0).GetOffset(),
+        )
+
+    def test_address_range_list(self):
+        """Make sure the SBAddressRangeList works by adding and getting 
ranges."""
+        range1 = lldb.SBAddressRange(0x00000400, 8)
+        range2 = lldb.SBAddressRange(0x00000800, 16)
+        range3 = lldb.SBAddressRange(0x00001000, 32)
+
+        range_list = lldb.SBAddressRangeList()
+        self.assertEqual(range_list.GetSize(), 0)
+
+        range_list.Append(range1)
+        range_list.Append(range2)
+        range_list.Append(range3)
+        self.assertEqual(range_list.GetSize(), 3)
+
+        range1_copy = lldb.SBAddressRange()
+        range_list.GetAddressRangeAtIndex(0, range1_copy)
+        self.assertEqual(range1.GetByteSize(), range1_copy.GetByteSize())
+        self.assertEqual(
+            range1.GetBaseAddress().GetOffset(),
+            range1_copy.GetBaseAddress().GetOffset(),
+        )
+
+        range2_copy = lldb.SBAddressRange()
+        range_list.GetAddressRangeAtIndex(1, range2_copy)
+        self.assertEqual(range2.GetByteSize(), range2_copy.GetByteSize())
+        self.assertEqual(
+            range2.GetBaseAddress().GetOffset(),
+            range2_copy.GetBaseAddress().GetOffset(),
+        )
+
+        range3_copy = lldb.SBAddressRange()
+        range_list.GetAddressRangeAtIndex(2, range3_copy)
+        self.assertEqual(range3.GetByteSize(), range3_copy.GetByteSize())
+        self.assertEqual(
+            range3.GetBaseAddress().GetOffset(),
+            range3_copy.GetBaseAddress().GetOffset(),
+        )
+
+        range_list.Clear()
+        self.assertEqual(range_list.GetSize(), 0)
diff --git a/lldb/test/API/python_api/address_range/main.cpp 
b/lldb/test/API/python_api/address_range/main.cpp
new file mode 100644
index 0000000000000..cdd6db20bfaf0
--- /dev/null
+++ b/lldb/test/API/python_api/address_range/main.cpp
@@ -0,0 +1,5 @@
+#include <iostream>
+
+int main() {
+    std::cout << "Hello World!" << std::endl;    
+}

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

Reply via email to