[Lldb-commits] [lldb] Add AddressRange to SB API (PR #92014)
Miro Bucko via lldb-commits
lldb-commits at lists.llvm.org
Thu May 16 06:57:08 PDT 2024
https://github.com/mbucko updated https://github.com/llvm/llvm-project/pull/92014
>From dc84f8b94c2500b3c1caf2b0c053069989cfc082 Mon Sep 17 00:00:00 2001
From: Miro Bucko <mbucko at 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:
llvm-lit -sv llvm-project/lldb/test/API/python_api/address_range/TestAddressRange.py
Reviewers: clayborg
Subscribers: lldb-commits
Tasks:
Tags:
---
lldb/bindings/headers.swig | 2 +
.../interface/SBAddressRangeDocstrings.i | 3 +
.../interface/SBAddressRangeExtensions.i | 1 +
.../interface/SBAddressRangeListDocstrings.i | 3 +
.../interface/SBAddressRangeListExtensions.i | 25 +++
lldb/bindings/interfaces.swig | 6 +
lldb/include/lldb/API/LLDB.h | 2 +
lldb/include/lldb/API/SBAddress.h | 1 +
lldb/include/lldb/API/SBAddressRange.h | 66 ++++++
lldb/include/lldb/API/SBAddressRangeList.h | 59 ++++++
lldb/include/lldb/API/SBBlock.h | 4 +
lldb/include/lldb/API/SBDefines.h | 2 +
lldb/include/lldb/API/SBFunction.h | 3 +
lldb/include/lldb/API/SBStream.h | 2 +
lldb/include/lldb/Core/AddressRange.h | 12 ++
lldb/include/lldb/Symbol/Block.h | 2 +
lldb/include/lldb/lldb-forward.h | 3 +
lldb/source/API/CMakeLists.txt | 2 +
lldb/source/API/SBAddressRange.cpp | 102 ++++++++++
lldb/source/API/SBAddressRangeList.cpp | 134 +++++++++++++
lldb/source/API/SBBlock.cpp | 9 +
lldb/source/API/SBFunction.cpp | 10 +
lldb/source/Core/AddressRange.cpp | 15 ++
lldb/source/Symbol/Block.cpp | 17 ++
.../API/python_api/address_range/Makefile | 3 +
.../address_range/TestAddressRange.py | 189 ++++++++++++++++++
.../API/python_api/address_range/main.cpp | 8 +
27 files changed, 685 insertions(+)
create mode 100644 lldb/bindings/interface/SBAddressRangeDocstrings.i
create mode 100644 lldb/bindings/interface/SBAddressRangeExtensions.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/SBAddressRangeExtensions.i b/lldb/bindings/interface/SBAddressRangeExtensions.i
new file mode 100644
index 0000000000000..bca359868232d
--- /dev/null
+++ b/lldb/bindings/interface/SBAddressRangeExtensions.i
@@ -0,0 +1 @@
+STRING_EXTENSION_OUTSIDE(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..08bfa6d9aef60
--- /dev/null
+++ b/lldb/bindings/interface/SBAddressRangeListExtensions.i
@@ -0,0 +1,25 @@
+STRING_EXTENSION_OUTSIDE(SBAddressRangeList)
+
+%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')
+
+ def __getitem__(self, idx):
+ '''Get the address range at a given index in an lldb.SBAddressRangeList object.'''
+ if type(idx) == int:
+ if idx >= self.GetSize():
+ raise IndexError("list index out of range")
+ return self.GetAddressRangeAtIndex(idx)
+ else:
+ print("error: unsupported idx type: %s" % type(key))
+ return None
+ %}
+#endif
+}
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index a31a0b4af1eb6..500bc6c1a2433 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -12,6 +12,8 @@
/* Docstrings for SB classes and methods */
%include "./interface/SBAddressDocstrings.i"
+%include "./interface/SBAddressRangeDocstrings.i"
+%include "./interface/SBAddressRangeListDocstrings.i"
%include "./interface/SBAttachInfoDocstrings.i"
%include "./interface/SBBlockDocstrings.i"
%include "./interface/SBBreakpointDocstrings.i"
@@ -86,6 +88,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"
@@ -162,6 +166,8 @@
/* Extensions for SB classes */
%include "./interface/SBAddressExtensions.i"
+%include "./interface/SBAddressRangeExtensions.i"
+%include "./interface/SBAddressRangeListExtensions.i"
%include "./interface/SBBlockExtensions.i"
%include "./interface/SBBreakpointExtensions.i"
%include "./interface/SBBreakpointListExtensions.i"
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..6cd864a34187c
--- /dev/null
+++ b/lldb/include/lldb/API/SBAddressRange.h
@@ -0,0 +1,66 @@
+//===-- 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::SBAddress addr, lldb::addr_t byte_size);
+
+ ~SBAddressRange();
+
+ const lldb::SBAddressRange &operator=(const lldb::SBAddressRange &rhs);
+
+ void Clear();
+
+ /// Check the address range refers to a valid base address and has a byte
+ /// size greater than zero.
+ ///
+ /// \return
+ /// True if the address range is valid, false otherwise.
+ 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;
+
+ bool operator==(const SBAddressRange &rhs);
+
+ bool operator!=(const SBAddressRange &rhs);
+
+ bool GetDescription(lldb::SBStream &description);
+
+protected:
+ friend class SBAddressRangeList;
+ friend class SBBlock;
+ friend class SBFunction;
+
+private:
+ AddressRangeUP m_opaque_up;
+};
+
+} // 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..e289a655ebebc
--- /dev/null
+++ b/lldb/include/lldb/API/SBAddressRangeList.h
@@ -0,0 +1,59 @@
+//===-- 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();
+
+ SBAddressRange GetAddressRangeAtIndex(uint64_t idx);
+
+ void Append(const lldb::SBAddressRange &addr_range);
+
+ void Append(const lldb::SBAddressRangeList &addr_range_list);
+
+ bool GetDescription(lldb::SBStream &description);
+
+protected:
+ const AddressRangeListImpl *operator->() const;
+
+ const AddressRangeListImpl &operator*() const;
+
+private:
+ friend class SBBlock;
+ friend class SBProcess;
+
+ lldb_private::AddressRanges &ref();
+
+ 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..de4bb22be2692 100644
--- a/lldb/include/lldb/API/SBBlock.h
+++ b/lldb/include/lldb/API/SBBlock.h
@@ -9,6 +9,8 @@
#ifndef LLDB_API_SBBLOCK_H
#define LLDB_API_SBBLOCK_H
+#include "lldb/API/SBAddressRange.h"
+#include "lldb/API/SBAddressRangeList.h"
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBTarget.h"
@@ -52,6 +54,8 @@ class LLDB_API SBBlock {
lldb::SBAddress GetRangeEndAddress(uint32_t idx);
+ lldb::SBAddressRangeList GetRanges();
+
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/API/SBStream.h b/lldb/include/lldb/API/SBStream.h
index 0e33f05b69916..71caf41fd7549 100644
--- a/lldb/include/lldb/API/SBStream.h
+++ b/lldb/include/lldb/API/SBStream.h
@@ -62,6 +62,8 @@ class LLDB_API SBStream {
protected:
friend class SBAddress;
+ friend class SBAddressRange;
+ friend class SBAddressRangeList;
friend class SBBlock;
friend class SBBreakpoint;
friend class SBBreakpointLocation;
diff --git a/lldb/include/lldb/Core/AddressRange.h b/lldb/include/lldb/Core/AddressRange.h
index 4a33c2d795876..e59e0ece852b0 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
@@ -236,12 +238,22 @@ class AddressRange {
/// The new size in bytes of this address range.
void SetByteSize(lldb::addr_t byte_size) { m_byte_size = byte_size; }
+ bool operator==(const AddressRange &rhs);
+
+ bool operator!=(const AddressRange &rhs);
+
protected:
// Member variables
Address m_base_addr; ///< The section offset base address of this range.
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/Symbol/Block.h b/lldb/include/lldb/Symbol/Block.h
index 02fd2add53103..c9c4d5ad767d7 100644
--- a/lldb/include/lldb/Symbol/Block.h
+++ b/lldb/include/lldb/Symbol/Block.h
@@ -355,6 +355,8 @@ class Block : public UserID, public SymbolContextScope {
// be able to get at any of the address ranges in a block.
bool GetRangeAtIndex(uint32_t range_idx, AddressRange &range);
+ AddressRanges GetRanges();
+
bool GetStartAddress(Address &addr);
void SetDidParseVariables(bool b, bool set_children);
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 76b42ecf63f91..ffa18147fc4f2 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -41,6 +41,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..af164733575ff
--- /dev/null
+++ b/lldb/source/API/SBAddressRange.cpp
@@ -0,0 +1,102 @@
+//===-- 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 "Utils.h"
+#include "lldb/API/SBAddress.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Utility/Instrumentation.h"
+#include "lldb/Utility/Stream.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::SBAddress addr, lldb::addr_t byte_size)
+ : m_opaque_up(std::make_unique<AddressRange>(addr.ref(), byte_size)) {
+ LLDB_INSTRUMENT_VA(this, 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;
+}
+
+bool SBAddressRange::operator==(const SBAddressRange &rhs) {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ if (!IsValid() || !rhs.IsValid())
+ return false;
+ return m_opaque_up->operator==(*(rhs.m_opaque_up));
+}
+
+bool SBAddressRange::operator!=(const SBAddressRange &rhs) {
+ LLDB_INSTRUMENT_VA(this, rhs);
+
+ return !(*this == rhs);
+}
+
+void SBAddressRange::Clear() {
+ LLDB_INSTRUMENT_VA(this);
+
+ m_opaque_up.reset();
+}
+
+bool SBAddressRange::IsValid() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ return m_opaque_up && m_opaque_up->IsValid();
+}
+
+lldb::SBAddress SBAddressRange::GetBaseAddress() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ if (!IsValid())
+ return lldb::SBAddress();
+ return lldb::SBAddress(m_opaque_up->GetBaseAddress());
+}
+
+lldb::addr_t SBAddressRange::GetByteSize() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ if (!IsValid())
+ return 0;
+ return m_opaque_up->GetByteSize();
+}
+
+bool SBAddressRange::GetDescription(SBStream &description) {
+ LLDB_INSTRUMENT_VA(this, description);
+
+ Stream &stream = description.ref();
+
+ if (!IsValid()) {
+ stream << "Invalid address range";
+ return true;
+ }
+ m_opaque_up->DumpDebug(&stream);
+ return true;
+}
diff --git a/lldb/source/API/SBAddressRangeList.cpp b/lldb/source/API/SBAddressRangeList.cpp
new file mode 100644
index 0000000000000..3a55492cb40f6
--- /dev/null
+++ b/lldb/source/API/SBAddressRangeList.cpp
@@ -0,0 +1,134 @@
+//===-- 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 "Utils.h"
+#include "lldb/API/SBAddressRange.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Utility/Instrumentation.h"
+#include "lldb/Utility/Stream.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) { 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(); }
+
+ lldb_private::AddressRange GetAddressRangeAtIndex(size_t index) {
+ if (index >= GetSize())
+ return AddressRange();
+ return m_ranges[index];
+ }
+
+ AddressRanges &Ref() { return m_ranges; }
+
+private:
+ AddressRanges m_ranges;
+};
+
+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();
+}
+
+SBAddressRange SBAddressRangeList::GetAddressRangeAtIndex(uint64_t idx) {
+ LLDB_INSTRUMENT_VA(this, idx);
+
+ SBAddressRange sb_addr_range;
+ (*sb_addr_range.m_opaque_up) = m_opaque_up->GetAddressRangeAtIndex(idx);
+ return sb_addr_range;
+}
+
+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.m_opaque_up);
+}
+
+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;
+}
+
+AddressRanges &SBAddressRangeList::ref() { return m_opaque_up->Ref(); }
+
+bool SBAddressRangeList::GetDescription(SBStream &description) {
+ LLDB_INSTRUMENT_VA(this, description);
+
+ const uint32_t num_ranges = GetSize();
+ for (uint32_t i = 0; i < num_ranges; ++i) {
+ GetAddressRangeAtIndex(i).GetDescription(description);
+ }
+ return true;
+}
diff --git a/lldb/source/API/SBBlock.cpp b/lldb/source/API/SBBlock.cpp
index 7d7565340836b..e175b6a3634ff 100644
--- a/lldb/source/API/SBBlock.cpp
+++ b/lldb/source/API/SBBlock.cpp
@@ -219,6 +219,15 @@ lldb::SBAddress SBBlock::GetRangeEndAddress(uint32_t idx) {
return sb_addr;
}
+lldb::SBAddressRangeList SBBlock::GetRanges() {
+ LLDB_INSTRUMENT_VA(this);
+
+ lldb::SBAddressRangeList sb_ranges;
+ if (m_opaque_ptr)
+ sb_ranges.ref() = m_opaque_ptr->GetRanges();
+ return sb_ranges;
+}
+
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..d80ffaf580140 100644
--- a/lldb/source/API/SBFunction.cpp
+++ b/lldb/source/API/SBFunction.cpp
@@ -160,6 +160,16 @@ SBAddress SBFunction::GetEndAddress() {
return addr;
}
+lldb::SBAddressRange SBFunction::GetRange() {
+ LLDB_INSTRUMENT_VA(this);
+
+ lldb::SBAddressRange range;
+ if (m_opaque_ptr)
+ (*range.m_opaque_up) = 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..16ff2f0476ba6 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;
@@ -203,3 +207,14 @@ void AddressRange::DumpDebug(Stream *s) const {
static_cast<void *>(m_base_addr.GetSection().get()),
m_base_addr.GetOffset(), GetByteSize());
}
+
+bool AddressRange::operator==(const AddressRange &rhs) {
+ if (!IsValid() || !rhs.IsValid())
+ return false;
+ return m_base_addr == rhs.GetBaseAddress() &&
+ m_byte_size == rhs.GetByteSize();
+}
+
+bool AddressRange::operator!=(const AddressRange &rhs) {
+ return !(*this == rhs);
+}
diff --git a/lldb/source/Symbol/Block.cpp b/lldb/source/Symbol/Block.cpp
index 6eeabe0ff5e4d..15306a361b3a1 100644
--- a/lldb/source/Symbol/Block.cpp
+++ b/lldb/source/Symbol/Block.cpp
@@ -300,6 +300,7 @@ uint32_t Block::GetRangeIndexContainingAddress(const Address &addr) {
return UINT32_MAX;
}
+
bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
if (range_idx < m_ranges.GetSize()) {
Function *function = CalculateSymbolContextFunction();
@@ -314,6 +315,22 @@ bool Block::GetRangeAtIndex(uint32_t range_idx, AddressRange &range) {
return false;
}
+AddressRanges Block::GetRanges() {
+ AddressRanges ranges;
+ Function *function = CalculateSymbolContextFunction();
+ if (!function)
+ return ranges;
+ for (size_t i = 0, e = m_ranges.GetSize(); i < e; ++i) {
+ ranges.emplace_back();
+ auto& range = ranges.back();
+ const Range &vm_range = m_ranges.GetEntryRef(i);
+ range.GetBaseAddress() = function->GetAddressRange().GetBaseAddress();
+ range.GetBaseAddress().Slide(vm_range.GetRangeBase());
+ range.SetByteSize(vm_range.GetByteSize());
+ }
+ return ranges;
+}
+
bool Block::GetStartAddress(Address &addr) {
if (m_ranges.IsEmpty())
return false;
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..18e4987d65edf
--- /dev/null
+++ b/lldb/test/API/python_api/address_range/TestAddressRange.py
@@ -0,0 +1,189 @@
+"""
+Test SBAddressRange APIs.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+
+
+class AddressRangeTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ self.bp1 = target.BreakpointCreateByName("main", "a.out")
+ self.bp2 = target.BreakpointCreateByName("foo", "a.out")
+ self.bp3 = target.BreakpointCreateByName("bar", "a.out")
+
+ self.assertTrue(self.bp1.IsValid())
+ self.assertTrue(self.bp2.IsValid())
+ self.assertTrue(self.bp3.IsValid())
+
+ self.addr1 = self.bp1.GetLocationAtIndex(0).GetAddress()
+ self.addr2 = self.bp2.GetLocationAtIndex(0).GetAddress()
+ self.addr3 = self.bp3.GetLocationAtIndex(0).GetAddress()
+
+ self.assertTrue(self.addr1.IsValid())
+ self.assertTrue(self.addr2.IsValid())
+ self.assertTrue(self.addr3.IsValid())
+
+ 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(self.addr1, 8)
+ self.assertEqual(range.IsValid(), True)
+ self.assertEqual(range.GetBaseAddress(), self.addr1)
+ self.assertEqual(range.GetByteSize(), 8)
+
+ def test_address_range_clear(self):
+ """Make sure the clear method works."""
+ range = lldb.SBAddressRange(self.addr1, 8)
+ self.assertEqual(range.IsValid(), True)
+ self.assertEqual(range.GetBaseAddress(), self.addr1)
+ self.assertEqual(range.GetByteSize(), 8)
+
+ range.Clear()
+ self.assertEqual(range.IsValid(), False)
+
+ def test_function(self):
+ """Make sure the range works in SBFunction APIs."""
+
+ # Setup breakpoints in main
+ loc = self.bp1.GetLocationAtIndex(0)
+ loc_addr = loc.GetAddress()
+ func = loc_addr.GetFunction()
+ range = func.GetRange()
+ 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."""
+ loc = self.bp1.GetLocationAtIndex(0)
+ loc_addr = loc.GetAddress()
+ block = loc_addr.GetBlock()
+
+ ranges = block.GetRanges()
+ self.assertEqual(ranges.GetSize(), 1)
+
+ range = ranges.GetAddressRangeAtIndex(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(self.addr1, 8)
+ range2 = lldb.SBAddressRange(self.addr2, 16)
+ range3 = lldb.SBAddressRange(self.addr3, 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)
+ self.assertRaises(IndexError, lambda: range_list[3])
+
+ range1_copy = range_list.GetAddressRangeAtIndex(0)
+ self.assertEqual(range1.GetByteSize(), range1_copy.GetByteSize())
+ self.assertEqual(
+ range1.GetBaseAddress().GetOffset(),
+ range1_copy.GetBaseAddress().GetOffset(),
+ )
+
+ range2_copy = range_list.GetAddressRangeAtIndex(1)
+ self.assertEqual(range2.GetByteSize(), range2_copy.GetByteSize())
+ self.assertEqual(
+ range2.GetBaseAddress().GetOffset(),
+ range2_copy.GetBaseAddress().GetOffset(),
+ )
+
+ range3_copy = range_list.GetAddressRangeAtIndex(2)
+ 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)
+
+ def test_address_range_list_len(self):
+ """Make sure the len() operator works."""
+ range = lldb.SBAddressRange(self.addr1, 8)
+
+ range_list = lldb.SBAddressRangeList()
+ self.assertEqual(len(range_list), 0)
+
+ range_list.Append(range)
+ self.assertEqual(len(range_list), 1)
+
+ def test_address_range_list_iterator(self):
+ """Make sure the SBAddressRangeList iterator works."""
+ range1 = lldb.SBAddressRange(self.addr1, 8)
+ range2 = lldb.SBAddressRange(self.addr2, 16)
+ range3 = lldb.SBAddressRange(self.addr3, 32)
+
+ range_list = lldb.SBAddressRangeList()
+ range_list.Append(range1)
+ range_list.Append(range2)
+ range_list.Append(range3)
+ self.assertEqual(range_list.GetSize(), 3)
+
+ # Test the iterator
+ for range in range_list:
+ self.assertTrue(range.IsValid())
+
+ def test_address_range_print(self):
+ """Make sure the SBAddressRange can be printed."""
+ range = lldb.SBAddressRange(self.addr1, 8)
+
+ range_str = str(range)
+
+ offset_str = hex(self.addr1.GetOffset())[2:]
+ self.assertIn(offset_str, range_str)
+
+ byte_size_str = hex(range.GetByteSize())[2:]
+ self.assertIn(byte_size_str, range_str)
+
+ def test_address_range_list_print(self):
+ """Make sure the SBAddressRangeList can be printed."""
+ range1 = lldb.SBAddressRange(self.addr1, 8)
+ range2 = lldb.SBAddressRange(self.addr2, 16)
+ range3 = lldb.SBAddressRange(self.addr3, 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)
+
+ range_list_str = str(range_list)
+ self.assertIn("3 address ranges:", range_list_str)
+ self.assertEqual(range_list_str.count("AddressRange"), 3)
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..b6eaec4a23699
--- /dev/null
+++ b/lldb/test/API/python_api/address_range/main.cpp
@@ -0,0 +1,8 @@
+void foo() {}
+void bar() {}
+
+int main() {
+ foo();
+ bar();
+ return 0;
+}
More information about the lldb-commits
mailing list