[lldb] Add SBAddressRange and SBAddressRangeList to SB API (#93836)
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. This is a second attempt to land the reverted PR #92014.
This commit is contained in:
parent
5f243b3fff
commit
48175a5d9f
@ -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"
|
||||
|
3
lldb/bindings/interface/SBAddressRangeDocstrings.i
Normal file
3
lldb/bindings/interface/SBAddressRangeDocstrings.i
Normal file
@ -0,0 +1,3 @@
|
||||
%feature("docstring",
|
||||
"API clients can get address range information."
|
||||
) lldb::SBAddressRange;
|
11
lldb/bindings/interface/SBAddressRangeExtensions.i
Normal file
11
lldb/bindings/interface/SBAddressRangeExtensions.i
Normal file
@ -0,0 +1,11 @@
|
||||
%extend lldb::SBAddressRange {
|
||||
#ifdef SWIGPYTHON
|
||||
%pythoncode%{
|
||||
def __repr__(self):
|
||||
import lldb
|
||||
stream = lldb.SBStream()
|
||||
self.GetDescription(stream, lldb.target if lldb.target else lldb.SBTarget())
|
||||
return stream.GetData()
|
||||
%}
|
||||
#endif
|
||||
}
|
3
lldb/bindings/interface/SBAddressRangeListDocstrings.i
Normal file
3
lldb/bindings/interface/SBAddressRangeListDocstrings.i
Normal file
@ -0,0 +1,3 @@
|
||||
%feature("docstring",
|
||||
"Represents a list of :py:class:`SBAddressRange`."
|
||||
) lldb::SBAddressRangeList;
|
29
lldb/bindings/interface/SBAddressRangeListExtensions.i
Normal file
29
lldb/bindings/interface/SBAddressRangeListExtensions.i
Normal file
@ -0,0 +1,29 @@
|
||||
%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 not isinstance(idx, int):
|
||||
raise TypeError("unsupported index type: %s" % type(idx))
|
||||
count = len(self)
|
||||
if not (-count <= idx < count):
|
||||
raise IndexError("list index out of range")
|
||||
idx %= count
|
||||
return self.GetAddressRangeAtIndex(idx)
|
||||
|
||||
def __repr__(self):
|
||||
import lldb
|
||||
stream = lldb.SBStream()
|
||||
self.GetDescription(stream, lldb.target if lldb.target else lldb.SBTarget())
|
||||
return stream.GetData()
|
||||
%}
|
||||
#endif
|
||||
}
|
@ -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"
|
||||
@ -163,6 +167,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"
|
||||
|
@ -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"
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
lldb::SBLineEntry GetLineEntry();
|
||||
|
||||
protected:
|
||||
friend class SBAddressRange;
|
||||
friend class SBBlock;
|
||||
friend class SBBreakpoint;
|
||||
friend class SBBreakpointLocation;
|
||||
|
66
lldb/include/lldb/API/SBAddressRange.h
Normal file
66
lldb/include/lldb/API/SBAddressRange.h
Normal file
@ -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, const SBTarget target);
|
||||
|
||||
private:
|
||||
friend class SBAddressRangeList;
|
||||
friend class SBBlock;
|
||||
friend class SBFunction;
|
||||
friend class SBProcess;
|
||||
|
||||
AddressRangeUP m_opaque_up;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_API_SBADDRESSRANGE_H
|
54
lldb/include/lldb/API/SBAddressRangeList.h
Normal file
54
lldb/include/lldb/API/SBAddressRangeList.h
Normal file
@ -0,0 +1,54 @@
|
||||
//===-- 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"
|
||||
|
||||
namespace lldb_private {
|
||||
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, const SBTarget &target);
|
||||
|
||||
private:
|
||||
friend class SBBlock;
|
||||
friend class SBProcess;
|
||||
|
||||
std::unique_ptr<lldb_private::AddressRangeListImpl> m_opaque_up;
|
||||
};
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
#endif // LLDB_API_SBADDRESSRANGELIST_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 @@ public:
|
||||
|
||||
lldb::SBAddress GetRangeEndAddress(uint32_t idx);
|
||||
|
||||
lldb::SBAddressRangeList GetRanges();
|
||||
|
||||
uint32_t GetRangeIndexForBlockAddress(lldb::SBAddress block_addr);
|
||||
|
||||
lldb::SBValueList GetVariables(lldb::SBFrame &frame, bool arguments,
|
||||
|
@ -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;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define LLDB_API_SBFUNCTION_H
|
||||
|
||||
#include "lldb/API/SBAddress.h"
|
||||
#include "lldb/API/SBAddressRangeList.h"
|
||||
#include "lldb/API/SBDefines.h"
|
||||
#include "lldb/API/SBInstructionList.h"
|
||||
|
||||
@ -44,6 +45,8 @@ public:
|
||||
|
||||
lldb::SBAddress GetEndAddress();
|
||||
|
||||
lldb::SBAddressRangeList GetRanges();
|
||||
|
||||
const char *GetArgumentName(uint32_t arg_idx);
|
||||
|
||||
uint32_t GetPrologueByteSize();
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
|
||||
protected:
|
||||
friend class SBAddress;
|
||||
friend class SBAddressRange;
|
||||
friend class SBAddressRangeList;
|
||||
friend class SBBlock;
|
||||
friend class SBBreakpoint;
|
||||
friend class SBBreakpointLocation;
|
||||
|
@ -943,6 +943,7 @@ public:
|
||||
|
||||
protected:
|
||||
friend class SBAddress;
|
||||
friend class SBAddressRange;
|
||||
friend class SBBlock;
|
||||
friend class SBBreakpoint;
|
||||
friend class SBBreakpointList;
|
||||
|
@ -86,6 +86,8 @@ public:
|
||||
/// (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,24 @@ public:
|
||||
/// The new size in bytes of this address range.
|
||||
void SetByteSize(lldb::addr_t byte_size) { m_byte_size = byte_size; }
|
||||
|
||||
bool GetDescription(Stream *s, Target *target) const;
|
||||
|
||||
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
|
||||
|
51
lldb/include/lldb/Core/AddressRangeListImpl.h
Normal file
51
lldb/include/lldb/Core/AddressRangeListImpl.h
Normal file
@ -0,0 +1,51 @@
|
||||
//===-- AddressRangeListImpl.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_CORE_ADDRESSRANGELISTIMPL_H
|
||||
#define LLDB_CORE_ADDRESSRANGELISTIMPL_H
|
||||
|
||||
#include "lldb/Core/AddressRange.h"
|
||||
#include <cstddef>
|
||||
|
||||
namespace lldb {
|
||||
class SBBlock;
|
||||
}
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class AddressRangeListImpl {
|
||||
public:
|
||||
AddressRangeListImpl();
|
||||
|
||||
AddressRangeListImpl(const AddressRangeListImpl &rhs) = default;
|
||||
|
||||
AddressRangeListImpl &operator=(const AddressRangeListImpl &rhs);
|
||||
|
||||
size_t GetSize() const;
|
||||
|
||||
void Reserve(size_t capacity);
|
||||
|
||||
void Append(const AddressRange &sb_region);
|
||||
|
||||
void Append(const AddressRangeListImpl &list);
|
||||
|
||||
void Clear();
|
||||
|
||||
lldb_private::AddressRange GetAddressRangeAtIndex(size_t index);
|
||||
|
||||
private:
|
||||
friend class lldb::SBBlock;
|
||||
|
||||
AddressRanges &ref();
|
||||
|
||||
AddressRanges m_ranges;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // LLDB_CORE_ADDRESSRANGE_H
|
@ -355,6 +355,8 @@ public:
|
||||
// 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);
|
||||
|
@ -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;
|
||||
|
@ -42,6 +42,8 @@ set_target_properties(lldb-sbapi-dwarf-enums PROPERTIES FOLDER "LLDB/Tablegennin
|
||||
|
||||
add_lldb_library(liblldb SHARED ${option_framework}
|
||||
SBAddress.cpp
|
||||
SBAddressRange.cpp
|
||||
SBAddressRangeList.cpp
|
||||
SBAttachInfo.cpp
|
||||
SBBlock.cpp
|
||||
SBBreakpoint.cpp
|
||||
|
103
lldb/source/API/SBAddressRange.cpp
Normal file
103
lldb/source/API/SBAddressRange.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
//===-- 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/API/SBTarget.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,
|
||||
const SBTarget target) {
|
||||
LLDB_INSTRUMENT_VA(this, description, target);
|
||||
|
||||
Stream &stream = description.ref();
|
||||
if (!IsValid()) {
|
||||
stream << "<invalid>";
|
||||
return true;
|
||||
}
|
||||
m_opaque_up->GetDescription(&stream, target.GetSP().get());
|
||||
return true;
|
||||
}
|
94
lldb/source/API/SBAddressRangeList.cpp
Normal file
94
lldb/source/API/SBAddressRangeList.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
//===-- 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/API/SBTarget.h"
|
||||
#include "lldb/Core/AddressRangeListImpl.h"
|
||||
#include "lldb/Utility/Instrumentation.h"
|
||||
#include "lldb/Utility/Stream.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
SBAddressRangeList::SBAddressRangeList()
|
||||
: m_opaque_up(std::make_unique<AddressRangeListImpl>()) {
|
||||
LLDB_INSTRUMENT_VA(this);
|
||||
}
|
||||
|
||||
SBAddressRangeList::SBAddressRangeList(const SBAddressRangeList &rhs)
|
||||
: m_opaque_up(std::make_unique<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.m_opaque_up);
|
||||
}
|
||||
|
||||
bool SBAddressRangeList::GetDescription(SBStream &description,
|
||||
const SBTarget &target) {
|
||||
LLDB_INSTRUMENT_VA(this, description, target);
|
||||
|
||||
const uint32_t num_ranges = GetSize();
|
||||
bool is_first = true;
|
||||
Stream &stream = description.ref();
|
||||
stream << "[";
|
||||
for (uint32_t i = 0; i < num_ranges; ++i) {
|
||||
if (is_first) {
|
||||
is_first = false;
|
||||
} else {
|
||||
stream.Printf(", ");
|
||||
}
|
||||
GetAddressRangeAtIndex(i).GetDescription(description, target);
|
||||
}
|
||||
stream << "]";
|
||||
return true;
|
||||
}
|
@ -13,6 +13,7 @@
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/API/SBValue.h"
|
||||
#include "lldb/Core/AddressRange.h"
|
||||
#include "lldb/Core/AddressRangeListImpl.h"
|
||||
#include "lldb/Core/ValueObjectVariable.h"
|
||||
#include "lldb/Symbol/Block.h"
|
||||
#include "lldb/Symbol/Function.h"
|
||||
@ -219,6 +220,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.m_opaque_up->ref() = m_opaque_ptr->GetRanges();
|
||||
return sb_ranges;
|
||||
}
|
||||
|
||||
uint32_t SBBlock::GetRangeIndexForBlockAddress(lldb::SBAddress block_addr) {
|
||||
LLDB_INSTRUMENT_VA(this, block_addr);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/API/SBFunction.h"
|
||||
#include "lldb/API/SBAddressRange.h"
|
||||
#include "lldb/API/SBProcess.h"
|
||||
#include "lldb/API/SBStream.h"
|
||||
#include "lldb/Core/Disassembler.h"
|
||||
@ -160,6 +161,19 @@ SBAddress SBFunction::GetEndAddress() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
lldb::SBAddressRangeList SBFunction::GetRanges() {
|
||||
LLDB_INSTRUMENT_VA(this);
|
||||
|
||||
lldb::SBAddressRangeList ranges;
|
||||
if (m_opaque_ptr) {
|
||||
lldb::SBAddressRange range;
|
||||
(*range.m_opaque_up) = m_opaque_ptr->GetAddressRange();
|
||||
ranges.Append(std::move(range));
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
||||
|
||||
const char *SBFunction::GetArgumentName(uint32_t arg_idx) {
|
||||
LLDB_INSTRUMENT_VA(this, arg_idx);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "lldb/Utility/FileSpec.h"
|
||||
#include "lldb/Utility/Stream.h"
|
||||
#include "lldb/lldb-defines.h"
|
||||
#include "lldb/lldb-types.h"
|
||||
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
@ -145,6 +146,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 +208,41 @@ void AddressRange::DumpDebug(Stream *s) const {
|
||||
static_cast<void *>(m_base_addr.GetSection().get()),
|
||||
m_base_addr.GetOffset(), GetByteSize());
|
||||
}
|
||||
|
||||
bool AddressRange::GetDescription(Stream *s, Target *target) const {
|
||||
addr_t start_addr = m_base_addr.GetLoadAddress(target);
|
||||
if (start_addr != LLDB_INVALID_ADDRESS) {
|
||||
// We have a valid target and the address was resolved, or we have a base
|
||||
// address with no section. Just print out a raw address range: [<addr>,
|
||||
// <addr>)
|
||||
s->Printf("[0x%" PRIx64 "-0x%" PRIx64 ")", start_addr,
|
||||
start_addr + GetByteSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Either no target or the address wasn't resolved, print as
|
||||
// <module>[<file-addr>-<file-addr>)
|
||||
const char *file_name = "";
|
||||
const auto section_sp = m_base_addr.GetSection();
|
||||
if (section_sp) {
|
||||
if (const auto object_file = section_sp->GetObjectFile())
|
||||
file_name = object_file->GetFileSpec().GetFilename().AsCString();
|
||||
}
|
||||
start_addr = m_base_addr.GetFileAddress();
|
||||
const addr_t end_addr = (start_addr == LLDB_INVALID_ADDRESS)
|
||||
? LLDB_INVALID_ADDRESS
|
||||
: start_addr + GetByteSize();
|
||||
s->Printf("%s[0x%" PRIx64 "-0x%" PRIx64 ")", file_name, start_addr, end_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
50
lldb/source/Core/AddressRangeListImpl.cpp
Normal file
50
lldb/source/Core/AddressRangeListImpl.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
//===-- AddressRangeListImpl.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/Core/AddressRangeListImpl.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
AddressRangeListImpl::AddressRangeListImpl() : m_ranges() {}
|
||||
|
||||
AddressRangeListImpl &
|
||||
AddressRangeListImpl::operator=(const AddressRangeListImpl &rhs) {
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
m_ranges = rhs.m_ranges;
|
||||
return *this;
|
||||
}
|
||||
|
||||
size_t AddressRangeListImpl::GetSize() const { return m_ranges.size(); }
|
||||
|
||||
void AddressRangeListImpl::Reserve(size_t capacity) {
|
||||
m_ranges.reserve(capacity);
|
||||
}
|
||||
|
||||
void AddressRangeListImpl::Append(const AddressRange &sb_region) {
|
||||
m_ranges.emplace_back(sb_region);
|
||||
}
|
||||
|
||||
void AddressRangeListImpl::Append(const AddressRangeListImpl &list) {
|
||||
Reserve(GetSize() + list.GetSize());
|
||||
|
||||
for (const auto &range : list.m_ranges)
|
||||
Append(range);
|
||||
}
|
||||
|
||||
void AddressRangeListImpl::Clear() { m_ranges.clear(); }
|
||||
|
||||
lldb_private::AddressRange
|
||||
AddressRangeListImpl::GetAddressRangeAtIndex(size_t index) {
|
||||
if (index >= GetSize())
|
||||
return AddressRange();
|
||||
return m_ranges[index];
|
||||
}
|
||||
|
||||
AddressRanges &AddressRangeListImpl::ref() { return m_ranges; }
|
@ -23,6 +23,7 @@ endif()
|
||||
add_lldb_library(lldbCore
|
||||
Address.cpp
|
||||
AddressRange.cpp
|
||||
AddressRangeListImpl.cpp
|
||||
AddressResolver.cpp
|
||||
AddressResolverFileLine.cpp
|
||||
Communication.cpp
|
||||
|
@ -314,6 +314,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;
|
||||
|
3
lldb/test/API/python_api/address_range/Makefile
Normal file
3
lldb/test/API/python_api/address_range/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
262
lldb/test/API/python_api/address_range/TestAddressRange.py
Normal file
262
lldb/test/API/python_api/address_range/TestAddressRange.py
Normal file
@ -0,0 +1,262 @@
|
||||
"""
|
||||
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")
|
||||
|
||||
self.target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(self.target, VALID_TARGET)
|
||||
self.launch_info = self.target.GetLaunchInfo()
|
||||
self.launch_info.SetWorkingDirectory(self.get_process_working_directory())
|
||||
|
||||
self.bp1 = self.target.BreakpointCreateByName("main", "a.out")
|
||||
self.bp2 = self.target.BreakpointCreateByName("foo", "a.out")
|
||||
self.bp3 = self.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()
|
||||
ranges = func.GetRanges()
|
||||
self.assertEqual(ranges.GetSize(), 1)
|
||||
|
||||
range = ranges.GetAddressRangeAtIndex(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."""
|
||||
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_invalid(self):
|
||||
"""Make sure the SBAddressRange can be printed when invalid."""
|
||||
range = lldb.SBAddressRange()
|
||||
self.assertEqual(str(range), "<invalid>")
|
||||
|
||||
def test_address_range_print_resolved(self):
|
||||
"""Make sure the SBAddressRange can be printed when resolved."""
|
||||
lldb.target = self.target
|
||||
error = lldb.SBError()
|
||||
process = self.target.Launch(self.launch_info, error)
|
||||
self.assertTrue(error.Success(), "Make sure process launched successfully")
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
|
||||
script = (
|
||||
"script "
|
||||
+ "bp = lldb.target.GetBreakpointAtIndex(0);"
|
||||
+ "loc = bp.GetLocationAtIndex(0);"
|
||||
+ "loc_addr = loc.GetAddress();"
|
||||
+ "func = loc_addr.GetFunction();"
|
||||
+ "range = func.GetRanges().GetAddressRangeAtIndex(0);"
|
||||
+ "print(range)"
|
||||
)
|
||||
|
||||
interp = self.dbg.GetCommandInterpreter()
|
||||
result = lldb.SBCommandReturnObject()
|
||||
interp.HandleCommand(script, result, False)
|
||||
self.assertTrue(result.Succeeded(), "script command succeeded")
|
||||
# [0x1000-0x2000] // Resolved with target or addresses without sections
|
||||
self.assertRegex(result.GetOutput(), "^\[0x[0-9a-f]+\-0x[0-9a-f]+\)$")
|
||||
process.Kill()
|
||||
|
||||
def test_address_range_print_no_section_resolved(self):
|
||||
"""Make sure the SBAddressRange can be printed with no secion."""
|
||||
lldb.target = self.target
|
||||
error = lldb.SBError()
|
||||
process = self.target.Launch(self.launch_info, error)
|
||||
self.assertTrue(error.Success(), "Make sure process launched successfully")
|
||||
self.assertTrue(process, PROCESS_IS_VALID)
|
||||
self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
|
||||
|
||||
loc = self.bp1.GetLocationAtIndex(0)
|
||||
loc_addr = loc.GetAddress()
|
||||
func = loc_addr.GetFunction()
|
||||
range = func.GetRanges().GetAddressRangeAtIndex(0)
|
||||
|
||||
addr = lldb.SBAddress()
|
||||
addr.SetAddress(lldb.SBSection(), range.GetBaseAddress().GetOffset())
|
||||
self.assertFalse(addr.GetSection().IsValid())
|
||||
range = lldb.SBAddressRange(addr, range.GetByteSize())
|
||||
|
||||
range_str = str(range)
|
||||
# [0x1000-0x2000] // Resolved with target or addresses without sections
|
||||
self.assertRegex(range_str, "^\[0x[0-9a-f]+\-0x[0-9a-f]+\)$")
|
||||
process.Kill()
|
||||
|
||||
def test_address_range_print_not_resolved(self):
|
||||
"""Make sure the SBAddressRange can be printed when not resolved."""
|
||||
range = lldb.SBAddressRange(self.addr1, 8)
|
||||
range_str = str(range)
|
||||
# a.out[0x1000-0x2000] // Without target
|
||||
self.assertRegex(range_str, "^a.out\[0x[0-9a-f]+\-0x[0-9a-f]+\)$")
|
||||
|
||||
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)
|
||||
self.dbg.SetAsync(True)
|
||||
|
||||
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.assertTrue(range_list_str.startswith("["))
|
||||
self.assertGreater(range_list_str.count(","), 1)
|
||||
self.assertTrue(range_list_str.endswith("]"))
|
||||
|
||||
def test_address_range_list_indexing(self):
|
||||
"""Make sure the SBAddressRangeList can be printed."""
|
||||
range1 = lldb.SBAddressRange(self.addr1, 8)
|
||||
range2 = lldb.SBAddressRange(self.addr2, 16)
|
||||
range_list = lldb.SBAddressRangeList()
|
||||
range_list.Append(range1)
|
||||
range_list.Append(range2)
|
||||
|
||||
self.assertEqual(range_list.GetSize(), 2)
|
||||
self.assertRaises(IndexError, lambda: range_list[2])
|
||||
self.assertRaises(TypeError, lambda: range_list["0"])
|
||||
self.assertEqual(range_list[0], range1)
|
||||
self.assertEqual(range_list[1], range2)
|
||||
self.assertEqual(range_list[-1], range2)
|
||||
self.assertEqual(range_list[-2], range1)
|
8
lldb/test/API/python_api/address_range/main.cpp
Normal file
8
lldb/test/API/python_api/address_range/main.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
void foo() {}
|
||||
void bar() {}
|
||||
|
||||
int main() {
|
||||
foo();
|
||||
bar();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user