diff options
69 files changed, 3326 insertions, 698 deletions
diff --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h index 632f7aabfa2..d2eb79b0371 100644 --- a/lldb/include/lldb/API/LLDB.h +++ b/lldb/include/lldb/API/LLDB.h @@ -24,6 +24,7 @@ #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBCommunication.h" #include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBData.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" diff --git a/lldb/include/lldb/API/SBAddress.h b/lldb/include/lldb/API/SBAddress.h index fbe1f6a5832..e8a32a654ed 100644 --- a/lldb/include/lldb/API/SBAddress.h +++ b/lldb/include/lldb/API/SBAddress.h @@ -106,6 +106,7 @@ protected: friend class SBSymbolContext; friend class SBTarget; friend class SBThread; + friend class SBValue; #ifndef SWIG diff --git a/lldb/include/lldb/API/SBData.h b/lldb/include/lldb/API/SBData.h new file mode 100644 index 00000000000..63673153460 --- /dev/null +++ b/lldb/include/lldb/API/SBData.h @@ -0,0 +1,136 @@ +//===-- SBData.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBData_h_ +#define LLDB_SBData_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBData +{ +public: + + SBData (); + + SBData (const SBData &rhs); + +#ifndef SWIG + const SBData & + operator = (const SBData &rhs); +#endif + + ~SBData (); + + uint8_t + GetAddressByteSize (); + + void + Clear (); + + bool + IsValid(); + + size_t + GetByteSize (); + + lldb::ByteOrder + GetByteOrder(); + + float + GetFloat (lldb::SBError& error, uint32_t offset); + + double + GetDouble (lldb::SBError& error, uint32_t offset); + + long double + GetLongDouble (lldb::SBError& error, uint32_t offset); + + lldb::addr_t + GetAddress (lldb::SBError& error, uint32_t offset); + + uint8_t + GetUnsignedInt8 (lldb::SBError& error, uint32_t offset); + + uint16_t + GetUnsignedInt16 (lldb::SBError& error, uint32_t offset); + + uint32_t + GetUnsignedInt32 (lldb::SBError& error, uint32_t offset); + + uint64_t + GetUnsignedInt64 (lldb::SBError& error, uint32_t offset); + + int8_t + GetSignedInt8 (lldb::SBError& error, uint32_t offset); + + int16_t + GetSignedInt16 (lldb::SBError& error, uint32_t offset); + + int32_t + GetSignedInt32 (lldb::SBError& error, uint32_t offset); + + int64_t + GetSignedInt64 (lldb::SBError& error, uint32_t offset); + + const char* + GetString (lldb::SBError& error, uint32_t offset); + + size_t + ReadRawData (lldb::SBError& error, + uint32_t offset, + void *buf, + size_t size); + + bool + GetDescription (lldb::SBStream &description); + + // it would be nice to have SetData(SBError, const void*, size_t) when endianness and address size can be + // inferred from the existing DataExtractor, but having two SetData() signatures triggers a SWIG bug where + // the typemap isn't applied before resolving the overload, and thus the right function never gets called + void + SetData(lldb::SBError& error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); + + // see SetData() for why we don't have Append(const void* buf, size_t size) + bool + Append(const SBData& rhs); + +protected: + +#ifndef SWIG + // Mimic shared pointer... + lldb_private::DataExtractor * + get() const; + + lldb_private::DataExtractor * + operator->() const; + + lldb::DataExtractorSP & + operator*(); + + const lldb::DataExtractorSP & + operator*() const; +#endif + + SBData (const lldb::DataExtractorSP &data_sp); + + void + SetOpaque (const lldb::DataExtractorSP &data_sp); + +private: + friend class SBValue; + + lldb::DataExtractorSP m_opaque_sp; +}; + + +} // namespace lldb + +#endif // LLDB_SBData_h_ diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h index 72e6785ed58..553462c621c 100644 --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -34,6 +34,7 @@ class SBCommandInterpreter; class SBCommandReturnObject; class SBCommunication; class SBCompileUnit; +class SBData; class SBDebugger; class SBError; class SBEvent; diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h index df26704e29a..8b91f28941a 100644 --- a/lldb/include/lldb/API/SBError.h +++ b/lldb/include/lldb/API/SBError.h @@ -72,6 +72,7 @@ protected: #ifndef SWIG friend class SBArguments; + friend class SBData; friend class SBDebugger; friend class SBCommunication; friend class SBHostOS; diff --git a/lldb/include/lldb/API/SBStream.h b/lldb/include/lldb/API/SBStream.h index ba533f8436a..5b912a7ca6c 100644 --- a/lldb/include/lldb/API/SBStream.h +++ b/lldb/include/lldb/API/SBStream.h @@ -62,6 +62,7 @@ protected: friend class SBBreakpoint; friend class SBBreakpointLocation; friend class SBCompileUnit; + friend class SBData; friend class SBEvent; friend class SBFrame; friend class SBFunction; diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h index 4851e43b418..44ec2cdb8a3 100644 --- a/lldb/include/lldb/API/SBValue.h +++ b/lldb/include/lldb/API/SBValue.h @@ -10,14 +10,10 @@ #ifndef LLDB_SBValue_h_ #define LLDB_SBValue_h_ +#include "lldb/API/SBData.h" #include "lldb/API/SBDefines.h" #include "lldb/API/SBType.h" -#include <stdio.h> - -#ifndef SWIG -class lldb_private::SyntheticScriptProvider; -#endif namespace lldb { @@ -130,6 +126,13 @@ public: lldb::SBValue CreateValueFromAddress(const char* name, lldb::addr_t address, const SBType& type); + + // this has no address! GetAddress() and GetLoadAddress() as well as AddressOf() + // on the return of this call all return invalid + lldb::SBValue + CreateValueFromData (const char* name, + const SBData& data, + const SBType& type); //------------------------------------------------------------------ /// Get a child value by index from a value. @@ -207,7 +210,51 @@ public: lldb::SBValue AddressOf(); + + lldb::addr_t + GetLoadAddress(); + + lldb::SBAddress + GetAddress(); + //------------------------------------------------------------------ + /// Get an SBData wrapping what this SBValue points to. + /// + /// This method will dereference the current SBValue, if its + /// data type is a T* or T[], and extract item_count elements + /// of type T from it, copying their contents in an SBData. + /// + /// @param[in] item_idx + /// The index of the first item to retrieve. For an array + /// this is equivalent to array[item_idx], for a pointer + /// to *(pointer + item_idx). In either case, the measurement + /// unit for item_idx is the sizeof(T) rather than the byte + /// + /// @param[in] item_count + /// How many items should be copied into the output. By default + /// only one item is copied, but more can be asked for. + /// + /// @return + /// An SBData with the contents of the copied items, on success. + /// An empty SBData otherwise. + //------------------------------------------------------------------ + lldb::SBData + GetPointeeData (uint32_t item_idx = 0, + uint32_t item_count = 1); + + //------------------------------------------------------------------ + /// Get an SBData wrapping the contents of this SBValue. + /// + /// This method will read the contents of this object in memory + /// and copy them into an SBData for future use. + /// + /// @return + /// An SBData with the contents of this SBValue, on success. + /// An empty SBData otherwise. + //------------------------------------------------------------------ + lldb::SBData + GetData (); + uint32_t GetNumChildren (); @@ -245,15 +292,24 @@ public: GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes); SBValue (const lldb::ValueObjectSP &value_sp); - + +#ifndef SWIG + // this must be defined in the .h file because synthetic children as implemented in the core + // currently rely on being able to extract the SharedPointer out of an SBValue. if the implementation + // is deferred to the .cpp file instead of being inlined here, the platform will fail to link + // correctly. however, this is temporary till a better general solution is found. FIXME + const lldb::ValueObjectSP& + get_sp() const + { + return m_opaque_sp; + } +#endif + protected: friend class SBValueList; friend class SBFrame; #ifndef SWIG - // need this to decapsulate the SP from here - friend class lldb_private::SyntheticScriptProvider; - // Mimic shared pointer... lldb_private::ValueObject * get() const; diff --git a/lldb/include/lldb/Core/DataExtractor.h b/lldb/include/lldb/Core/DataExtractor.h index e33ee46d11b..8a5b8aeeb3f 100644 --- a/lldb/include/lldb/Core/DataExtractor.h +++ b/lldb/include/lldb/Core/DataExtractor.h @@ -364,7 +364,10 @@ public: /// The size in bytes of address values that will be extracted. //------------------------------------------------------------------ uint8_t - GetAddressByteSize () const; + GetAddressByteSize () const + { + return m_addr_size; + } //------------------------------------------------------------------ /// Get the number of bytes contained in this object. @@ -373,7 +376,10 @@ public: /// The total number of bytes of data this object refers to. //------------------------------------------------------------------ size_t - GetByteSize () const; + GetByteSize () const + { + return m_end - m_start; + } //------------------------------------------------------------------ /// Extract a C string from \a *offset_ptr. @@ -480,7 +486,10 @@ public: /// object's data, or NULL of there is no data in this object. //------------------------------------------------------------------ const uint8_t * - GetDataEnd () const; + GetDataEnd () const + { + return m_end; + } //------------------------------------------------------------------ /// Get the shared data offset. @@ -503,7 +512,10 @@ public: /// object's data, or NULL of there is no data in this object. //------------------------------------------------------------------ const uint8_t * - GetDataStart () const; + GetDataStart () const + { + return m_start; + } //------------------------------------------------------------------ @@ -519,7 +531,7 @@ public: /// unmodified. /// /// @return - /// The integer value that was extracted, or zero on failure. + /// The floating value that was extracted, or zero on failure. //------------------------------------------------------------------ float GetFloat (uint32_t *offset_ptr) const; @@ -751,7 +763,10 @@ public: /// state. //------------------------------------------------------------------ lldb::ByteOrder - GetByteOrder() const; + GetByteOrder() const + { + return m_byte_order; + } //------------------------------------------------------------------ /// Extract a uint8_t value from \a *offset_ptr. @@ -1046,7 +1061,10 @@ public: /// The size in bytes to use when extracting addresses. //------------------------------------------------------------------ void - SetAddressByteSize (uint8_t addr_size); + SetAddressByteSize (uint8_t addr_size) + { + m_addr_size = addr_size; + } //------------------------------------------------------------------ /// Set data with a buffer that is caller owned. @@ -1139,7 +1157,10 @@ public: /// The byte order value to use when extracting data. //------------------------------------------------------------------ void - SetByteOrder (lldb::ByteOrder byte_order); + SetByteOrder (lldb::ByteOrder byte_order) + { + m_byte_order = byte_order; + } //------------------------------------------------------------------ /// Skip an LEB128 number at \a *offset_ptr. @@ -1170,7 +1191,10 @@ public: /// object, \b false otherwise. //------------------------------------------------------------------ bool - ValidOffset (uint32_t offset) const; + ValidOffset (uint32_t offset) const + { + return offset < GetByteSize(); + } //------------------------------------------------------------------ /// Test the availability of \a length bytes of data from \a offset. @@ -1182,6 +1206,15 @@ public: bool ValidOffsetForDataOfSize (uint32_t offset, uint32_t length) const; + size_t + Copy (DataExtractor& dest_data) const; + + bool + Append (DataExtractor& rhs); + + bool + Append (void* bytes, uint32_t length); + protected: //------------------------------------------------------------------ // Member variables diff --git a/lldb/include/lldb/Core/FormatClasses.h b/lldb/include/lldb/Core/FormatClasses.h index d29ba7ff2af..59906f1626f 100644 --- a/lldb/include/lldb/Core/FormatClasses.h +++ b/lldb/include/lldb/Core/FormatClasses.h @@ -76,10 +76,7 @@ struct ValueFormat { return m_format; } - - std::string - FormatObject(lldb::ValueObjectSP object); - + }; class SyntheticChildrenFrontEnd diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h index 2f58aecaf54..afe587a15b2 100644 --- a/lldb/include/lldb/Core/FormatManager.h +++ b/lldb/include/lldb/Core/FormatManager.h @@ -410,17 +410,17 @@ public: } lldb::FormatCategorySP - Category (const char* category_name = NULL, - bool can_create = true) + GetCategory (const char* category_name = NULL, + bool can_create = true) { if (!category_name) - return Category(m_default_category_name); - return Category(ConstString(category_name)); + return GetCategory(m_default_category_name); + return GetCategory(ConstString(category_name)); } lldb::FormatCategorySP - Category (const ConstString& category_name, - bool can_create = true); + GetCategory (const ConstString& category_name, + bool can_create = true); bool Get (ValueObject& valobj, diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 17960563fc9..afdb0e7f19e 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -679,23 +679,25 @@ public: bool UpdateValueIfNeeded (lldb::DynamicValueType use_dynamic, bool update_format = true); - void + bool UpdateFormatsIfNeeded(lldb::DynamicValueType use_dynamic = lldb::eNoDynamicValues); - DataExtractor & - GetDataExtractor (); - lldb::ValueObjectSP GetSP () { return m_manager->GetSharedPointer(this); } -protected: void - AddSyntheticChild (const ConstString &key, - ValueObject *valobj); -public: + SetName (const ConstString &name); + + lldb::addr_t + GetAddressOf (bool scalar_is_load_address = true, + AddressType *address_type = NULL); + + lldb::addr_t + GetPointerValue (AddressType *address_type = NULL); + lldb::ValueObjectSP GetSyntheticChild (const ConstString &key) const; @@ -762,6 +764,9 @@ public: return false; } + virtual SymbolContextScope * + GetSymbolContextScope(); + static void DumpValueObject (Stream &s, ValueObject *valobj) @@ -864,14 +869,22 @@ public: // if it is a char* and check_pointer is true, // it also checks that the pointer is valid bool - IsCStringContainer(bool check_pointer = false); + IsCStringContainer (bool check_pointer = false); void - ReadPointedString(Stream& s, - Error& error, - uint32_t max_length = 0, - bool honor_array = true, - lldb::Format item_format = lldb::eFormatCharArray); + ReadPointedString (Stream& s, + Error& error, + uint32_t max_length = 0, + bool honor_array = true, + lldb::Format item_format = lldb::eFormatCharArray); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + + virtual size_t + GetData (DataExtractor& data); bool GetIsConstant () const @@ -894,18 +907,6 @@ public: } void - SetIsExpressionResult(bool expr) - { - m_is_expression_result = expr; - } - - bool - GetIsExpressionResult() - { - return m_is_expression_result; - } - - void SetFormat (lldb::Format format) { if (format != m_format) @@ -968,11 +969,22 @@ public: GetNonBaseClassParent(); void - SetPointersPointToLoadAddrs (bool b) + SetAddressTypeOfChildren(AddressType at) { - m_pointers_point_to_load_addrs = b; + m_address_type_of_ptr_or_ref_children = at; } - + + AddressType + GetAddressTypeOfChildren() + { + if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) + { + if (m_parent) + return m_parent->GetAddressTypeOfChildren(); + } + return m_address_type_of_ptr_or_ref_children; + } + protected: typedef ClusterManager<ValueObject> ValueObjectManager; @@ -1021,19 +1033,21 @@ protected: m_value_did_change:1, m_children_count_valid:1, m_old_value_valid:1, - m_pointers_point_to_load_addrs:1, m_is_deref_of_parent:1, m_is_array_item_for_pointer:1, m_is_bitfield_for_scalar:1, m_is_expression_path_child:1, - m_is_child_at_offset:1, - m_is_expression_result:1; + m_is_child_at_offset:1; - // used to prevent endless looping into GetpPrintableRepresentation() + // used to prevent endless looping into GetPrintableRepresentation() uint32_t m_dump_printable_counter; + + AddressType m_address_type_of_ptr_or_ref_children; + friend class ClangExpressionDeclMap; // For GetValue friend class ClangExpressionVariable; // For SetName friend class Target; // For SetName + friend class ValueObjectConstResultImpl; //------------------------------------------------------------------ // Constructors and Destructors @@ -1046,7 +1060,8 @@ protected: // Use this constructor to create a "root variable object". The ValueObject will be locked to this context // through-out its lifespan. - ValueObject (ExecutionContextScope *exe_scope); + ValueObject (ExecutionContextScope *exe_scope, + AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad); // Use this constructor to create a ValueObject owned by another ValueObject. It will inherit the ExecutionContext // of its parent. @@ -1088,19 +1103,14 @@ protected: void ClearUserVisibleData(); - -public: void - SetName (const ConstString &name); + AddSyntheticChild (const ConstString &key, + ValueObject *valobj); + + DataExtractor & + GetDataExtractor (); - lldb::addr_t - GetPointerValue (AddressType &address_type, - bool scalar_is_load_address); - - lldb::addr_t - GetAddressOf (AddressType &address_type, - bool scalar_is_load_address); private: //------------------------------------------------------------------ // For ValueObject only diff --git a/lldb/include/lldb/Core/ValueObjectChild.h b/lldb/include/lldb/Core/ValueObjectChild.h index a6c9a36b7eb..df8012226c3 100644 --- a/lldb/include/lldb/Core/ValueObjectChild.h +++ b/lldb/include/lldb/Core/ValueObjectChild.h @@ -104,8 +104,9 @@ protected: // void // ReadValueFromMemory (ValueObject* parent, lldb::addr_t address); -private: +protected: friend class ValueObject; + friend class ValueObjectConstResult; ValueObjectChild (ValueObject &parent, clang::ASTContext *clang_ast, void *clang_type, @@ -115,7 +116,8 @@ private: uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool is_base_class, - bool is_deref_of_parent); + bool is_deref_of_parent, + AddressType child_ptr_or_ref_addr_type); DISALLOW_COPY_AND_ASSIGN (ValueObjectChild); }; diff --git a/lldb/include/lldb/Core/ValueObjectConstResult.h b/lldb/include/lldb/Core/ValueObjectConstResult.h index e82f28c7136..d82390ee291 100644 --- a/lldb/include/lldb/Core/ValueObjectConstResult.h +++ b/lldb/include/lldb/Core/ValueObjectConstResult.h @@ -16,10 +16,12 @@ // Project includes #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" + namespace lldb_private { //---------------------------------------------------------------------- -// A child of another ValueObject. +// A frozen ValueObject copied into host memory //---------------------------------------------------------------------- class ValueObjectConstResult : public ValueObject { @@ -27,14 +29,16 @@ public: static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, - uint32_t addr_byte_size); + uint32_t addr_byte_size, + lldb::addr_t address = LLDB_INVALID_ADDRESS); static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, - const DataExtractor &data); + const DataExtractor &data, + lldb::addr_t address = LLDB_INVALID_ADDRESS); static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, @@ -43,7 +47,8 @@ public: const ConstString &name, const lldb::DataBufferSP &result_data_sp, lldb::ByteOrder byte_order, - uint8_t addr_size); + uint8_t addr_size, + lldb::addr_t address = LLDB_INVALID_ADDRESS); static lldb::ValueObjectSP Create (ExecutionContextScope *exe_scope, @@ -91,7 +96,24 @@ public: void SetByteSize (size_t size); - + + virtual lldb::ValueObjectSP + Dereference (Error &error); + + virtual ValueObject * + CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index); + + virtual lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + + virtual lldb::ValueObjectSP + AddressOf (Error &error); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + protected: virtual bool UpdateValue (); @@ -106,17 +128,22 @@ protected: clang::ASTContext *m_clang_ast; // The clang AST that the clang type comes from ConstString m_type_name; uint32_t m_byte_size; + + ValueObjectConstResultImpl m_impl; private: + friend class ValueObjectConstResultImpl; ValueObjectConstResult (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, - uint32_t addr_byte_size); + uint32_t addr_byte_size, + lldb::addr_t address); ValueObjectConstResult (ExecutionContextScope *exe_scope, clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, - const DataExtractor &data); + const DataExtractor &data, + lldb::addr_t address); ValueObjectConstResult (ExecutionContextScope *exe_scope, clang::ASTContext *clang_ast, @@ -124,7 +151,8 @@ private: const ConstString &name, const lldb::DataBufferSP &result_data_sp, lldb::ByteOrder byte_order, - uint8_t addr_size); + uint8_t addr_size, + lldb::addr_t address); ValueObjectConstResult (ExecutionContextScope *exe_scope, clang::ASTContext *clang_ast, diff --git a/lldb/include/lldb/Core/ValueObjectConstResultChild.h b/lldb/include/lldb/Core/ValueObjectConstResultChild.h new file mode 100644 index 00000000000..3dcef1ff4e5 --- /dev/null +++ b/lldb/include/lldb/Core/ValueObjectConstResultChild.h @@ -0,0 +1,78 @@ +//===-- ValueObjectConstResultChild.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectConstResultChild_h_ +#define liblldb_ValueObjectConstResultChild_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A child of a ValueObjectConstResult. +//---------------------------------------------------------------------- +class ValueObjectConstResultChild : public ValueObjectChild +{ +public: + + ValueObjectConstResultChild (ValueObject &parent, + clang::ASTContext *clang_ast, + void *clang_type, + const ConstString &name, + uint32_t byte_size, + int32_t byte_offset, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool is_base_class, + bool is_deref_of_parent); + + virtual ~ValueObjectConstResultChild(); + + virtual lldb::ValueObjectSP + Dereference (Error &error); + + virtual ValueObject * + CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index); + + virtual lldb::clang_type_t + GetClangType () + { + return ValueObjectChild::GetClangType(); + } + + virtual lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + + virtual lldb::ValueObjectSP + AddressOf (Error &error); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + +protected: + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; + + DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResultChild); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultChild_h_ diff --git a/lldb/include/lldb/Core/ValueObjectConstResultImpl.h b/lldb/include/lldb/Core/ValueObjectConstResultImpl.h new file mode 100644 index 00000000000..1b9c63fa4fa --- /dev/null +++ b/lldb/include/lldb/Core/ValueObjectConstResultImpl.h @@ -0,0 +1,89 @@ +//===-- ValueObjectConstResultImpl.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectConstResultImpl_h_ +#define liblldb_ValueObjectConstResultImpl_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A class wrapping common implementation details for operations in +// ValueObjectConstResult ( & Child ) that may need to jump from the host +// memory space into the target's memory space +//---------------------------------------------------------------------- +class ValueObjectConstResultImpl +{ +public: + + ValueObjectConstResultImpl (ValueObject* valobj, + lldb::addr_t live_address = LLDB_INVALID_ADDRESS); + + virtual + ~ValueObjectConstResultImpl() + { + } + + lldb::ValueObjectSP + Dereference (Error &error); + + ValueObject * + CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index); + + lldb::ValueObjectSP + GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create); + + lldb::ValueObjectSP + AddressOf (Error &error); + + bool + NeedsDerefOnTarget() + { + m_impl_backend->UpdateValueIfNeeded(false); + return (m_impl_backend->GetValue().GetValueType() == Value::eValueTypeHostAddress); + } + + lldb::addr_t + GetLiveAddress() + { + return m_live_address; + } + + void + SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS) + { + m_live_address = addr; + } + + lldb::ValueObjectSP + DerefOnTarget(); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + +private: + + ValueObject *m_impl_backend; + lldb::addr_t m_live_address; + lldb::ValueObjectSP m_load_addr_backend; + lldb::ValueObjectSP m_address_of_backend; + + DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResultImpl); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultImpl_h_ diff --git a/lldb/include/lldb/Core/ValueObjectVariable.h b/lldb/include/lldb/Core/ValueObjectVariable.h index 2e525eab863..575d37ae1b3 100644 --- a/lldb/include/lldb/Core/ValueObjectVariable.h +++ b/lldb/include/lldb/Core/ValueObjectVariable.h @@ -54,6 +54,9 @@ public: virtual Module* GetModule(); + + virtual SymbolContextScope * + GetSymbolContextScope(); protected: virtual bool diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 21becb6f297..91b2b6dc010 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -10,8 +10,6 @@ #ifndef liblldb_ScriptInterpreter_h_ #define liblldb_ScriptInterpreter_h_ -#include "lldb/API/SBValue.h" - #include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Utility/PseudoTerminal.h" @@ -41,7 +39,7 @@ public: typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor); typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); - typedef lldb::SBValue* (*SWIGPythonCastPyObjectToSBValue) (void* data); + typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); typedef void (*SWIGPythonUpdateSynthProviderInstance) (void* data); typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, @@ -160,10 +158,10 @@ public: return 0; } - virtual void* + virtual lldb::ValueObjectSP GetChildAtIndex (void *implementor, uint32_t idx) { - return NULL; + return lldb::ValueObjectSP(); } virtual int @@ -177,12 +175,6 @@ public: { } - virtual lldb::SBValue* - CastPyObjectToSBValue (void* data) - { - return NULL; - } - virtual bool RunScriptBasedCommand(const char* impl_function, const char* args, diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index 8e5033b3c41..e90e7cdb86a 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -23,7 +23,7 @@ #include "lldb/Host/Terminal.h" namespace lldb_private { - + class ScriptInterpreterPython : public ScriptInterpreter { public: @@ -69,7 +69,7 @@ public: virtual uint32_t CalculateNumChildren (void *implementor); - virtual void* + virtual lldb::ValueObjectSP GetChildAtIndex (void *implementor, uint32_t idx); virtual int @@ -78,9 +78,6 @@ public: virtual void UpdateSynthProviderInstance (void* implementor); - virtual lldb::SBValue* - CastPyObjectToSBValue (void* data); - virtual bool RunScriptBasedCommand(const char* impl_function, const char* args, @@ -161,6 +158,28 @@ protected: RestoreTerminalState (); private: + + class Locker + { + public: + Locker (ScriptInterpreterPython *py_interpreter, + FILE* wait_msg_handle = NULL, + bool need_session = true); + + bool + HasAcquiredLock () + { + return m_release_lock; + } + + ~Locker (); + + private: + bool m_need_session; + bool m_release_lock; + ScriptInterpreterPython *m_python_interpreter; + FILE* m_tmp_fh; + }; static size_t InputReaderCallback (void *baton, @@ -181,7 +200,6 @@ private: bool m_valid_session; }; - } // namespace lldb_private diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index 71fa375f8b1..9d256b77540 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -285,6 +285,21 @@ public: static lldb::clang_type_t GetPointeeType (lldb::clang_type_t opaque_clang_qual_type); + + lldb::clang_type_t + GetArrayElementType (uint32_t& stride); + + static lldb::clang_type_t + GetArrayElementType (clang::ASTContext* ast, + lldb::clang_type_t opaque_clang_qual_type, + uint32_t& stride); + + lldb::clang_type_t + GetPointerType (); + + static lldb::clang_type_t + GetPointerType (clang::ASTContext *ast_context, + lldb::clang_type_t opaque_clang_qual_type); static lldb::clang_type_t RemoveFastQualifiers (lldb::clang_type_t); diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 290d03203b2..789eeb66cc7 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -91,7 +91,12 @@ public: { return m_max_children_display; } - + uint32_t + GetMaximumSizeOfStringSummary() + { + return m_max_strlen_length; + } + protected: void @@ -107,6 +112,7 @@ protected: OptionValueBoolean m_skip_prologue; PathMappingList m_source_map; uint32_t m_max_children_display; + uint32_t m_max_strlen_length; }; @@ -478,7 +484,8 @@ public: bool prefer_file_cache, void *dst, size_t dst_len, - Error &error); + Error &error, + lldb::addr_t *load_addr_ptr = NULL); size_t ReadScalarIntegerFromMemory (const Address& addr, diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index b14860cd56e..950796d67a0 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -354,6 +354,7 @@ namespace lldb { eArgTypeCount, eArgTypeEndAddress, eArgTypeExpression, + eArgTypeExpressionPath, eArgTypeExprFormat, eArgTypeFilename, eArgTypeFormat, @@ -376,6 +377,9 @@ namespace lldb { eArgTypePid, eArgTypePlugin, eArgTypeProcessName, + eArgTypePythonClass, + eArgTypePythonFunction, + eArgTypePythonScript, eArgTypeQueueName, eArgTypeRegisterName, eArgTypeRegularExpression, diff --git a/lldb/include/lldb/lldb-forward-rtti.h b/lldb/include/lldb/lldb-forward-rtti.h index b4eb8c6ee0e..b89d9579acb 100644 --- a/lldb/include/lldb/lldb-forward-rtti.h +++ b/lldb/include/lldb/lldb-forward-rtti.h @@ -34,6 +34,7 @@ namespace lldb { typedef SharedPtr<lldb_private::Connection>::Type ConnectionSP; typedef SharedPtr<lldb_private::CompileUnit>::Type CompUnitSP; typedef SharedPtr<lldb_private::DataBuffer>::Type DataBufferSP; + typedef SharedPtr<lldb_private::DataExtractor>::Type DataExtractorSP; typedef SharedPtr<lldb_private::Debugger>::Type DebuggerSP; typedef SharedPtr<lldb_private::Disassembler>::Type DisassemblerSP; typedef SharedPtr<lldb_private::DynamicLoader>::Type DynamicLoaderSP; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index e45f4de2286..c07af33ce20 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -181,6 +181,10 @@ class Value; class ValueFormat; class ValueList; class ValueObject; +class ValueObjectChild; +class ValueObjectConstResult; +class ValueObjectConstResultChild; +class ValueObjectConstResultImpl; class ValueObjectList; class Variable; class VariableList; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 27617389483..e61fa65c8e8 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -408,11 +408,15 @@ 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; }; 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; }; + 9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; }; + 9443B123140C26AB0013457C /* SBData.h in Headers */ = {isa = PBXBuildFile; fileRef = 9443B120140C18A90013457C /* SBData.h */; settings = {ATTRIBUTES = (Public, ); }; }; 94611EB213CCA4A4003A22AF /* RefCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94611EB113CCA4A4003A22AF /* RefCounter.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */; }; 9470A8F01402DFFB0056FF61 /* DataVisualization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9470A8EF1402DFFB0056FF61 /* DataVisualization.cpp */; }; + 949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */; }; 94B6E76213D88365005F417F /* ValueObjectSyntheticFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */; }; + 94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; }; 9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; }; @@ -1188,6 +1192,8 @@ 94031A9F13CF5B3D00DCFF3C /* PriorityPointerPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PriorityPointerPair.h; path = include/lldb/Utility/PriorityPointerPair.h; sourceTree = "<group>"; }; 9415F61613B2C0DC00A52B36 /* FormatManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = FormatManager.h; path = include/lldb/Core/FormatManager.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; }; + 9443B121140C18C10013457C /* SBData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBData.cpp; path = source/API/SBData.cpp; sourceTree = "<group>"; }; 94611EAF13CCA363003A22AF /* RefCounter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RefCounter.h; path = include/lldb/Utility/RefCounter.h; sourceTree = "<group>"; }; 94611EB113CCA4A4003A22AF /* RefCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RefCounter.cpp; path = source/Utility/RefCounter.cpp; sourceTree = "<group>"; }; 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; @@ -1196,12 +1202,18 @@ 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = "<group>"; }; 9470A8EE1402DF940056FF61 /* DataVisualization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataVisualization.h; path = include/lldb/Core/DataVisualization.h; sourceTree = "<group>"; }; 9470A8EF1402DFFB0056FF61 /* DataVisualization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataVisualization.cpp; path = source/Core/DataVisualization.cpp; sourceTree = "<group>"; }; + 949ADF001406F62E004833E1 /* ValueObjectConstResultImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultImpl.h; path = include/lldb/Core/ValueObjectConstResultImpl.h; sourceTree = "<group>"; }; + 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultImpl.cpp; path = source/Core/ValueObjectConstResultImpl.cpp; sourceTree = "<group>"; }; 94A8287514031D05006C37A8 /* FormatNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatNavigator.h; path = include/lldb/Core/FormatNavigator.h; sourceTree = "<group>"; }; 94A9112B13D5DEF80046D8A6 /* FormatClasses.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FormatClasses.h; path = include/lldb/Core/FormatClasses.h; sourceTree = "<group>"; }; 94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatClasses.cpp; path = source/Core/FormatClasses.cpp; sourceTree = "<group>"; }; 94B6E76013D8833C005F417F /* ValueObjectSyntheticFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectSyntheticFilter.h; path = include/lldb/Core/ValueObjectSyntheticFilter.h; sourceTree = "<group>"; }; 94B6E76113D88362005F417F /* ValueObjectSyntheticFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectSyntheticFilter.cpp; path = source/Core/ValueObjectSyntheticFilter.cpp; sourceTree = "<group>"; }; + 94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = "modify-python-lldb.py"; sourceTree = "<group>"; }; + 94E367CE140C4EEA001C7A5A /* python-typemaps.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-typemaps.swig"; sourceTree = "<group>"; }; 94EBAC8313D9EE26009BA64E /* PythonPointer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PythonPointer.h; path = include/lldb/Utility/PythonPointer.h; sourceTree = "<group>"; }; + 94FA3DDD1405D4E500833217 /* ValueObjectConstResultChild.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResultChild.h; path = include/lldb/Core/ValueObjectConstResultChild.h; sourceTree = "<group>"; }; + 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResultChild.cpp; path = source/Core/ValueObjectConstResultChild.cpp; sourceTree = "<group>"; }; 94FE476613FC1DA8001F8475 /* finish-swig-Python-LLDB.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "finish-swig-Python-LLDB.sh"; sourceTree = "<group>"; }; 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = "<group>"; }; 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = "<group>"; }; @@ -1651,6 +1663,8 @@ 260223E8115F06E500A601A2 /* SBCommunication.cpp */, 26DE205411618FB800A093E2 /* SBCompileUnit.h */, 26DE205E1161901B00A093E2 /* SBCompileUnit.cpp */, + 9443B120140C18A90013457C /* SBData.h */, + 9443B121140C18C10013457C /* SBData.cpp */, 9A9830FB1125FC5800A56CB0 /* SBDebugger.h */, 9A9830FA1125FC5800A56CB0 /* SBDebugger.cpp */, 2682F286115EF3BD00CCFF99 /* SBError.h */, @@ -1781,7 +1795,9 @@ 266960601199F4230075C61A /* build-swig-Python.sh */, 266960611199F4230075C61A /* edit-swig-python-wrapper-file.py */, 94FE476613FC1DA8001F8475 /* finish-swig-Python-LLDB.sh */, + 94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */, 9A48A3A7124AAA5A00922451 /* python-extensions.swig */, + 94E367CE140C4EEA001C7A5A /* python-typemaps.swig */, 94005E0313F438DF001EF42D /* python-wrapper.swig */, ); path = Python; @@ -2038,6 +2054,10 @@ 26BC7E9B10F1B85900F91463 /* ValueObjectChild.cpp */, 26424E3E125986D30016D82C /* ValueObjectConstResult.h */, 26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */, + 94FA3DDD1405D4E500833217 /* ValueObjectConstResultChild.h */, + 94FA3DDF1405D50300833217 /* ValueObjectConstResultChild.cpp */, + 949ADF001406F62E004833E1 /* ValueObjectConstResultImpl.h */, + 949ADF021406F648004833E1 /* ValueObjectConstResultImpl.cpp */, 4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */, 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */, 26BC7D8410F1B77400F91463 /* ValueObjectList.h */, @@ -2679,6 +2699,7 @@ 2668021E115FD13D008E1FE4 /* SBCommandReturnObject.h in Headers */, 2668021F115FD13D008E1FE4 /* SBCommunication.h in Headers */, 26DE205511618FB800A093E2 /* SBCompileUnit.h in Headers */, + 9443B123140C26AB0013457C /* SBData.h in Headers */, 26680220115FD13D008E1FE4 /* SBDebugger.h in Headers */, 26680221115FD13D008E1FE4 /* SBDefines.h in Headers */, 26680222115FD13D008E1FE4 /* SBError.h in Headers */, @@ -2988,6 +3009,7 @@ 268F9D55123AA16600B91E9B /* SBSymbolContextList.cpp in Sources */, 26C72C961243229A0068DC16 /* SBStream.cpp in Sources */, 26B1FA1413380E61002886E2 /* LLDBWrapPython.cpp in Sources */, + 9443B122140C18C40013457C /* SBData.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3312,6 +3334,9 @@ 9470A8F01402DFFB0056FF61 /* DataVisualization.cpp in Sources */, 26274FA214030EEF006BA130 /* OperatingSystemDarwinKernel.cpp in Sources */, 26274FA714030F79006BA130 /* DynamicLoaderDarwinKernel.cpp in Sources */, + 94FA3DE01405D50400833217 /* ValueObjectConstResultChild.cpp in Sources */, + 949ADF031406F648004833E1 /* ValueObjectConstResultImpl.cpp in Sources */, + 268ED0A5140FF54200DE830F /* DataEncoder.cpp in Sources */, 26A0DA4E140F7226006DA411 /* HashedNameToDIE.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme index afb96900b7d..6e12c06c956 100644 --- a/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme +++ b/lldb/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme - version = "1.8"> + version = "1.3"> <BuildAction parallelizeBuildables = "NO" buildImplicitDependencies = "YES"> @@ -28,6 +28,15 @@ buildConfiguration = "Debug"> <Testables> </Testables> + <MacroExpansion> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "26F5C26910F3D9A4009D5894" + BuildableName = "lldb" + BlueprintName = "lldb-tool" + ReferencedContainer = "container:lldb.xcodeproj"> + </BuildableReference> + </MacroExpansion> <CommandLineArguments> <CommandLineArgument argument = "/Volumes/work/gclayton/Documents/src/attach/a.out" @@ -79,7 +88,8 @@ customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach" buildConfiguration = "Debug" ignoresPersistentStateOnLaunch = "YES" - enablesOpenGLESFrameCapture = "YES"> + debugDocumentVersioning = "YES" + allowLocationSimulation = "YES"> <BuildableProductRunnable> <BuildableReference BuildableIdentifier = "primary" @@ -129,7 +139,8 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" buildConfiguration = "Release" - ignoresPersistentStateOnLaunch = "YES"> + ignoresPersistentStateOnLaunch = "YES" + debugDocumentVersioning = "YES"> <BuildableProductRunnable> <BuildableReference BuildableIdentifier = "primary" diff --git a/lldb/scripts/Python/build-swig-Python.sh b/lldb/scripts/Python/build-swig-Python.sh index 1b2897e3149..21ff0058fbe 100755 --- a/lldb/scripts/Python/build-swig-Python.sh +++ b/lldb/scripts/Python/build-swig-Python.sh @@ -46,6 +46,7 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/lldb.h"\ " ${SRC_ROOT}/include/lldb/API/SBCommandReturnObject.h"\ " ${SRC_ROOT}/include/lldb/API/SBCommunication.h"\ " ${SRC_ROOT}/include/lldb/API/SBCompileUnit.h"\ +" ${SRC_ROOT}/include/lldb/API/SBData.h"\ " ${SRC_ROOT}/include/lldb/API/SBDebugger.h"\ " ${SRC_ROOT}/include/lldb/API/SBError.h"\ " ${SRC_ROOT}/include/lldb/API/SBEvent.h"\ @@ -72,6 +73,40 @@ HEADER_FILES="${SRC_ROOT}/include/lldb/lldb.h"\ " ${SRC_ROOT}/include/lldb/API/SBValue.h"\ " ${SRC_ROOT}/include/lldb/API/SBValueList.h" +INTERFACE_FILES = "${SRC_ROOT}/scripts/Python/interface/SBAddress.i"\ +" ${SRC_ROOT}/scripts/Python/interface/SBBlock.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBBreakpoint.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBBreakpointLocation.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBBroadcaster.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBCommandInterpreter.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBCommandReturnObject.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBCommunication.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBCompileUnit.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBData.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBDebugger.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBError.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBEvent.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBFileSpec.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBFrame.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBFunction.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBHostOS.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBInputReader.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBInstruction.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBInstructionList.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBLineEntry.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBListener.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBModule.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBProcess.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBSourceManager.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBStream.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBStringList.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBSymbol.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBSymbolContext.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBTarget.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBThread.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBType.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBValue.i" \ +" ${SRC_ROOT}/scripts/Python/interface/SBValueList.i" if [ $Debug == 1 ] then @@ -79,6 +114,12 @@ then echo ${HEADER_FILES} fi +if [ $Debug == 1 ] +then + echo "SWIG interface files are:" + echo ${INTERFACE_FILES} +fi + NeedToUpdate=0 @@ -110,6 +151,23 @@ fi if [ $NeedToUpdate == 0 ] then + for intffile in ${INTERFACE_FILES} + do + if [ $intffile -nt ${swig_output_file} ] + then + NeedToUpdate=1 + if [ $Debug == 1 ] + then + echo "${intffile} is newer than ${swig_output_file}" + echo "swig file will need to be re-built." + fi + break + fi + done +fi + +if [ $NeedToUpdate == 0 ] +then if [ ${swig_input_file} -nt ${swig_output_file} ] then NeedToUpdate=1 diff --git a/lldb/scripts/Python/interface/SBData.i b/lldb/scripts/Python/interface/SBData.i new file mode 100644 index 00000000000..416afb6eab9 --- /dev/null +++ b/lldb/scripts/Python/interface/SBData.i @@ -0,0 +1,95 @@ +//===-- SWIG Interface for SBData -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +namespace lldb { + +class SBData +{ +public: + + SBData (); + + SBData (const SBData &rhs); + + ~SBData (); + + uint8_t + GetAddressByteSize (); + + void + Clear (); + + bool + IsValid(); + + size_t + GetByteSize (); + + lldb::ByteOrder + GetByteOrder(); + + float + GetFloat (lldb::SBError& error, uint32_t offset); + + double + GetDouble (lldb::SBError& error, uint32_t offset); + + long double + GetLongDouble (lldb::SBError& error, uint32_t offset); + + lldb::addr_t + GetAddress (lldb::SBError& error, uint32_t offset); + + uint8_t + GetUnsignedInt8 (lldb::SBError& error, uint32_t offset); + + uint16_t + GetUnsignedInt16 (lldb::SBError& error, uint32_t offset); + + uint32_t + GetUnsignedInt32 (lldb::SBError& error, uint32_t offset); + + uint64_t + GetUnsignedInt64 (lldb::SBError& error, uint32_t offset); + + int8_t + GetSignedInt8 (lldb::SBError& error, uint32_t offset); + + int16_t + GetSignedInt16 (lldb::SBError& error, uint32_t offset); + + int32_t + GetSignedInt32 (lldb::SBError& error, uint32_t offset); + + int64_t + GetSignedInt64 (lldb::SBError& error, uint32_t offset); + + const char* + GetString (lldb::SBError& error, uint32_t offset); + + bool + GetDescription (lldb::SBStream &description); + + size_t + ReadRawData (lldb::SBError& error, + uint32_t offset, + void *buf, + size_t size); + + void + SetData(lldb::SBError& error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); + + bool + Append(const SBData& rhs); + + +}; + +} // namespace lldb diff --git a/lldb/scripts/Python/interface/SBValue.i b/lldb/scripts/Python/interface/SBValue.i index d73e6012c62..e87241070cb 100644 --- a/lldb/scripts/Python/interface/SBValue.i +++ b/lldb/scripts/Python/interface/SBValue.i @@ -196,6 +196,11 @@ public: lldb::SBValue CreateValueFromAddress(const char* name, lldb::addr_t address, const SBType& type); + lldb::SBValue + CreateValueFromData (const char* name, + const SBData& data, + const SBType& type); + lldb::SBType GetType(); @@ -278,9 +283,57 @@ public: bool GetExpressionPath (lldb::SBStream &description); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Get an SBData wrapping what this SBValue points to. + /// + /// This method will dereference the current SBValue, if its + /// data type is a T* or T[], and extract item_count elements + /// of type T from it, copying their contents in an SBData. + /// + /// @param[in] item_idx + /// The index of the first item to retrieve. For an array + /// this is equivalent to array[item_idx], for a pointer + /// to *(pointer + item_idx). In either case, the measurement + /// unit for item_idx is the sizeof(T) rather than the byte + /// + /// @param[in] item_count + /// How many items should be copied into the output. By default + /// only one item is copied, but more can be asked for. + /// + /// @return + /// An SBData with the contents of the copied items, on success. + /// An empty SBData otherwise. + //------------------------------------------------------------------ + ") GetPointeeData; + lldb::SBData + GetPointeeData (uint32_t item_idx = 0, + uint32_t item_count = 1); + + %feature("docstring", " + //------------------------------------------------------------------ + /// Get an SBData wrapping the contents of this SBValue. + /// + /// This method will read the contents of this object in memory + /// and copy them into an SBData for future use. + /// + /// @return + /// An SBData with the contents of this SBValue, on success. + /// An empty SBData otherwise. + //------------------------------------------------------------------ + ") GetData; + lldb::SBData + GetData (); + + lldb::addr_t + GetLoadAddress(); + + lldb::SBAddress + GetAddress(); %feature("docstring", "Returns an expression path for this value." - ) GetValueForExpressionPath; + ) GetExpressionPath; bool GetExpressionPath (lldb::SBStream &description, bool qualify_cxx_base_classes); }; diff --git a/lldb/scripts/Python/python-extensions.swig b/lldb/scripts/Python/python-extensions.swig index 8943561b5be..64506994287 100644 --- a/lldb/scripts/Python/python-extensions.swig +++ b/lldb/scripts/Python/python-extensions.swig @@ -41,6 +41,13 @@ return PyString_FromString (description.GetData()); } } +%extend lldb::SBData { + PyObject *lldb::SBData::__repr__ (){ + lldb::SBStream description; + $self->GetDescription (description); + return PyString_FromString (description.GetData()); + } +} %extend lldb::SBDebugger { PyObject *lldb::SBDebugger::__repr__ (){ lldb::SBStream description; diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig index 964f96a57ef..3417c71ab35 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -540,7 +540,7 @@ LLDBSwigPython_UpdateSynthProviderInstance } -SWIGEXPORT lldb::SBValue* +SWIGEXPORT void* LLDBSWIGPython_CastPyObjectToSBValue ( PyObject* data diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig index 8f18bf33fd4..66ac7b67fd7 100644 --- a/lldb/scripts/lldb.swig +++ b/lldb/scripts/lldb.swig @@ -51,6 +51,7 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions #include "lldb/API/SBCommandReturnObject.h" #include "lldb/API/SBCommunication.h" #include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBData.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" @@ -78,25 +79,6 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions #include "lldb/API/SBValueList.h" %} -%{ -template<class T> -class not_owning_ap -{ -private: - std::auto_ptr<T> m_auto_ptr; -public: - explicit not_owning_ap (T* p=0) : m_auto_ptr(p) {} - not_owning_ap (not_owning_ap& a) : m_auto_ptr(a.m_auto_ptr) {} - template<class Y> - not_owning_ap (not_owning_ap<Y>& a) : m_auto_ptr(a.m_auto_ptr) {} - not_owning_ap (const not_owning_ap<T>& r) : m_auto_ptr(r.m_auto_ptr) {} - ~not_owning_ap() { m_auto_ptr.release(); } - T* get() const { return m_auto_ptr.get(); } - T& operator*() const { return *m_auto_ptr; } - void reset (T* p=0) { m_auto_ptr.release(); m_auto_ptr.reset(p); } -}; -%} - /* Various liblldb typedefs that SWIG needs to know about. */ #define __extension__ /* Undefine GCC keyword to make Swig happy when processing glibc's stdint.h. */ %include <stdint.h> @@ -119,6 +101,7 @@ public: %include "./Python/interface/SBCommandReturnObject.i" %include "./Python/interface/SBCommunication.i" %include "./Python/interface/SBCompileUnit.i" +%include "./Python/interface/SBData.i" %include "./Python/interface/SBDebugger.i" %include "./Python/interface/SBError.i" %include "./Python/interface/SBEvent.i" diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 5b3371b62bc..95e1cbc2ad2 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -334,7 +334,7 @@ LLDBSwigPythonCreateSyntheticProvider extern "C" uint32_t LLDBSwigPython_CalculateNumChildren (void *implementor); extern "C" void* LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); extern "C" int LLDBSwigPython_GetIndexOfChildWithName (void *implementor, const char* child_name); -extern "C" lldb::SBValue* LLDBSWIGPython_CastPyObjectToSBValue (void* data); +extern "C" void* LLDBSWIGPython_CastPyObjectToSBValue (void* data); extern "C" void LLDBSwigPython_UpdateSynthProviderInstance (void* implementor); extern "C" bool LLDBSwigPythonCallCommand diff --git a/lldb/source/API/SBData.cpp b/lldb/source/API/SBData.cpp new file mode 100644 index 00000000000..cee63164859 --- /dev/null +++ b/lldb/source/API/SBData.cpp @@ -0,0 +1,489 @@ +//===-- SBData.cpp ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/API/SBData.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBStream.h" + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" + +using namespace lldb; +using namespace lldb_private; + +SBData::SBData () +{ +} + +SBData::SBData (const lldb::DataExtractorSP& data_sp) : + m_opaque_sp (data_sp) +{ +} + +SBData::SBData(const SBData &rhs) : + m_opaque_sp (rhs.m_opaque_sp) +{ +} + +const SBData & +SBData::operator = (const SBData &rhs) +{ + if (this != &rhs) + m_opaque_sp = rhs.m_opaque_sp; + return *this; +} + +SBData::~SBData () +{ +} + +void +SBData::SetOpaque (const lldb::DataExtractorSP &data_sp) +{ + m_opaque_sp = data_sp; +} + +lldb_private::DataExtractor * +SBData::get() const +{ + return m_opaque_sp.get(); +} + +lldb_private::DataExtractor * +SBData::operator->() const +{ + return m_opaque_sp.operator->(); +} + +lldb::DataExtractorSP & +SBData::operator*() +{ + return m_opaque_sp; +} + +const lldb::DataExtractorSP & +SBData::operator*() const +{ + return m_opaque_sp; +} + +bool +SBData::IsValid() +{ + return m_opaque_sp.get() != NULL; +} + +uint8_t +SBData::GetAddressByteSize () +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint8_t value = 0; + if (m_opaque_sp.get()) + value = m_opaque_sp->GetAddressByteSize(); + if (log) + log->Printf ("SBData::GetAddressByteSize () => " + "(%i)", value); + return value; +} + +void +SBData::Clear () +{ + if (m_opaque_sp.get()) + m_opaque_sp->Clear(); +} + +size_t +SBData::GetByteSize () +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + size_t value = 0; + if (m_opaque_sp.get()) + value = m_opaque_sp->GetByteSize(); + if (log) + log->Printf ("SBData::GetByteSize () => " + "(%i)", value); + return value; +} + +lldb::ByteOrder +SBData::GetByteOrder () +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + lldb::ByteOrder value = eByteOrderInvalid; + if (m_opaque_sp.get()) + value = m_opaque_sp->GetByteOrder(); + if (log) + log->Printf ("SBData::GetByteOrder () => " + "(%i)", value); + return value; +} + +float +SBData::GetFloat (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + float value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetFloat(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetFloat (error=%p,offset=%d) => " + "(%f)", error.get(), offset, value); + return value; +} + +double +SBData::GetDouble (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + double value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetDouble(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetDouble (error=%p,offset=%d) => " + "(%f)", error.get(), offset, value); + return value; +} + +long double +SBData::GetLongDouble (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + long double value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetLongDouble(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetLongDouble (error=%p,offset=%d) => " + "(%lf)", error.get(), offset, value); + return value; +} + +lldb::addr_t +SBData::GetAddress (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + lldb::addr_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetAddress(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetAddress (error=%p,offset=%d) => " + "(%p)", error.get(), offset, (void*)value); + return value; +} + +uint8_t +SBData::GetUnsignedInt8 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint8_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU8(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt8 (error=%p,offset=%d) => " + "(%c)", error.get(), offset, value); + return value; +} + +uint16_t +SBData::GetUnsignedInt16 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint16_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU16(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt16 (error=%p,offset=%d) => " + "(%hd)", error.get(), offset, value); + return value; +} + +uint32_t +SBData::GetUnsignedInt32 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint32_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU32(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt32 (error=%p,offset=%d) => " + "(%d)", error.get(), offset, value); + return value; +} + +uint64_t +SBData::GetUnsignedInt64 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + uint64_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetU64(&offset); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetUnsignedInt64 (error=%p,offset=%d) => " + "(%q)", error.get(), offset, value); + return value; +} + +int8_t +SBData::GetSignedInt8 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int8_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int8_t)m_opaque_sp->GetMaxS64(&offset, 1); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt8 (error=%p,offset=%d) => " + "(%c)", error.get(), offset, value); + return value; +} + +int16_t +SBData::GetSignedInt16 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int16_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int16_t)m_opaque_sp->GetMaxS64(&offset, 2); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt16 (error=%p,offset=%d) => " + "(%hd)", error.get(), offset, value); + return value; +} + +int32_t +SBData::GetSignedInt32 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int32_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int32_t)m_opaque_sp->GetMaxS64(&offset, 4); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt32 (error=%p,offset=%d) => " + "(%d)", error.get(), offset, value); + return value; +} + +int64_t +SBData::GetSignedInt64 (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + int64_t value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = (int64_t)m_opaque_sp->GetMaxS64(&offset, 8); + if (offset == old_offset) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetSignedInt64 (error=%p,offset=%d) => " + "(%q)", error.get(), offset, value); + return value; +} + +const char* +SBData::GetString (lldb::SBError& error, uint32_t offset) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + const char* value = 0; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + value = m_opaque_sp->GetCStr(&offset); + if (offset == old_offset || (value == NULL)) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::GetString (error=%p,offset=%d) => " + "(%p)", error.get(), offset, value); + return value; +} + +bool +SBData::GetDescription (lldb::SBStream &description) +{ + if (m_opaque_sp) + { + description.ref(); + m_opaque_sp->Dump(description.get(), + 0, + lldb::eFormatBytesWithASCII, + 1, + m_opaque_sp->GetByteSize(), + 16, + LLDB_INVALID_ADDRESS, + 0, + 0); + } + else + description.Printf ("No Value"); + + return true; +} + +size_t +SBData::ReadRawData (lldb::SBError& error, + uint32_t offset, + void *buf, + size_t size) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + void* ok = NULL; + if (!m_opaque_sp.get()) + { + error.SetErrorString("no value to read from"); + } + else + { + uint32_t old_offset = offset; + ok = m_opaque_sp->GetU8(&offset, buf, size); + if ((offset == old_offset) || (ok == NULL)) + error.SetErrorString("unable to read data"); + } + if (log) + log->Printf ("SBData::ReadRawData (error=%p,offset=%d,buf=%p,size=%d) => " + "(%p)", error.get(), offset, buf, size, ok); + return ok ? size : 0; +} + +void +SBData::SetData(lldb::SBError& error, + const void *buf, + size_t size, + lldb::ByteOrder endian, + uint8_t addr_size) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (!m_opaque_sp.get()) + m_opaque_sp.reset(new DataExtractor(buf, size, endian, addr_size)); + else + m_opaque_sp->SetData(buf, size, endian); + if (log) + log->Printf ("SBData::SetData (error=%p,buf=%p,size=%d,endian=%d,addr_size=%c) => " + "(%p)", error.get(), buf, size, endian, addr_size, m_opaque_sp.get()); +} + +bool +SBData::Append(const SBData& rhs) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + bool value = false; + if (m_opaque_sp.get() && rhs.m_opaque_sp.get()) + value = m_opaque_sp.get()->Append(*rhs.m_opaque_sp); + if (log) + log->Printf ("SBData::Append (rhs=%p) => " + "(%s)", rhs.get(), value ? "true" : "false"); + return value; +}
\ No newline at end of file diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp index a58957b9a9b..ea7ebf8c13e 100644 --- a/lldb/source/API/SBValue.cpp +++ b/lldb/source/API/SBValue.cpp @@ -479,6 +479,38 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, const SB return result; } +lldb::SBValue +SBValue::CreateValueFromData (const char* name, + const SBData& data, + const SBType& type) +{ + SBValue result; + + AddressType addr_of_children_priv = eAddressTypeLoad; + + if (m_opaque_sp) + { + ValueObjectSP valobj_sp; + valobj_sp = ValueObjectConstResult::Create (m_opaque_sp->GetExecutionContextScope(), + type.m_opaque_sp->GetASTContext() , + type.m_opaque_sp->GetOpaqueQualType(), + ConstString(name), + *data.m_opaque_sp, + LLDB_INVALID_ADDRESS); + valobj_sp->SetAddressTypeOfChildren(addr_of_children_priv); + result = SBValue(valobj_sp); + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + { + if (result.IsValid()) + log->Printf ("SBValue(%p)::GetChildFromExpression => \"%s\"", m_opaque_sp.get(), result.m_opaque_sp.get()); + else + log->Printf ("SBValue(%p)::GetChildFromExpression => NULL", m_opaque_sp.get()); + } + return result; +} + SBValue SBValue::GetChildAtIndex (uint32_t idx) { @@ -812,9 +844,10 @@ SBValue::GetProcess() SBProcess result; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) { - result = SBProcess(lldb::ProcessSP(m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetProcessSP())); + result = SBProcess(lldb::ProcessSP(target->GetProcessSP())); } } LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -967,10 +1000,10 @@ SBValue::AddressOf() SBValue sb_value; if (m_opaque_sp) { - if (m_opaque_sp->GetUpdatePoint().GetTargetSP()) + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) { - Mutex::Locker api_locker (m_opaque_sp->GetUpdatePoint().GetTargetSP()->GetAPIMutex()); - + Mutex::Locker api_locker (target->GetAPIMutex()); Error error; sb_value = m_opaque_sp->AddressOf (error); } @@ -981,3 +1014,127 @@ SBValue::AddressOf() return sb_value; } + +lldb::addr_t +SBValue::GetLoadAddress() +{ + lldb::addr_t value = LLDB_INVALID_ADDRESS; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + Mutex::Locker api_locker (target->GetAPIMutex()); + const bool scalar_is_load_address = true; + AddressType addr_type; + value = m_opaque_sp->GetAddressOf(scalar_is_load_address, &addr_type); + if (addr_type == eAddressTypeFile) + { + Module* module = m_opaque_sp->GetModule(); + if (!module) + value = LLDB_INVALID_ADDRESS; + else + { + Address addr; + module->ResolveFileAddress(value, addr); + value = addr.GetLoadAddress(m_opaque_sp->GetUpdatePoint().GetTargetSP().get()); + } + } + else if (addr_type == eAddressTypeHost || addr_type == eAddressTypeInvalid) + value = LLDB_INVALID_ADDRESS; + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetLoadAddress () => (%llu)", m_opaque_sp.get(), value); + + return value; +} + +lldb::SBAddress +SBValue::GetAddress() +{ + Address addr; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + lldb::addr_t value = LLDB_INVALID_ADDRESS; + Mutex::Locker api_locker (target->GetAPIMutex()); + const bool scalar_is_load_address = true; + AddressType addr_type; + value = m_opaque_sp->GetAddressOf(scalar_is_load_address, &addr_type); + if (addr_type == eAddressTypeFile) + { + Module* module = m_opaque_sp->GetModule(); + if (module) + module->ResolveFileAddress(value, addr); + } + else if (addr_type == eAddressTypeLoad) + { + // no need to check the return value on this.. if it can actually do the resolve + // addr will be in the form (section,offset), otherwise it will simply be returned + // as (NULL, value) + addr.SetLoadAddress(value, target); + } + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetAddress () => (%s,%llu)", m_opaque_sp.get(), (addr.GetSection() ? addr.GetSection()->GetName().GetCString() : "NULL"), addr.GetOffset()); + return SBAddress(new Address(addr)); +} + +lldb::SBData +SBValue::GetPointeeData (uint32_t item_idx, + uint32_t item_count) +{ + lldb::SBData sb_data; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + DataExtractorSP data_sp(new DataExtractor()); + Mutex::Locker api_locker (target->GetAPIMutex()); + m_opaque_sp->GetPointeeData(*data_sp, item_idx, item_count); + if (data_sp->GetByteSize() > 0) + *sb_data = data_sp; + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetPointeeData (%d, %d) => SBData(%p)", + m_opaque_sp.get(), + item_idx, + item_count, + sb_data.get()); + + return sb_data; +} + +lldb::SBData +SBValue::GetData () +{ + lldb::SBData sb_data; + if (m_opaque_sp) + { + Target* target = m_opaque_sp->GetUpdatePoint().GetTargetSP().get(); + if (target) + { + DataExtractorSP data_sp(new DataExtractor()); + Mutex::Locker api_locker (target->GetAPIMutex()); + m_opaque_sp->GetData(*data_sp); + if (data_sp->GetByteSize() > 0) + *sb_data = data_sp; + } + } + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + if (log) + log->Printf ("SBValue(%p)::GetData () => SBData(%p)", + m_opaque_sp.get(), + sb_data.get()); + + return sb_data; +} diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 8f63bf29009..da0af986247 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1514,7 +1514,7 @@ public: OptionDefinition CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { - { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypeName, "Name of a Python function to use."}, + { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 694c904391e..4be9b8de3ad 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -321,9 +321,6 @@ CommandObjectExpression::EvaluateExpression { if (result_valobj_sp->GetError().Success()) { - - result_valobj_sp.get()->SetIsExpressionResult(true); - if (m_options.format != eFormatDefault) result_valobj_sp->SetFormat (m_options.format); diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index e12427a50c8..2e82df060c6 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -1082,8 +1082,8 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeNone, "If true, inline all child values into summary string."}, { LLDB_OPT_SET_2 , true, "summary-string", 's', required_argument, NULL, 0, eArgTypeSummaryString, "Summary string used to display text and object contents."}, - { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypeName, "Give a one-liner Python script as part of the command."}, - { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypeName, "Give the name of a Python function to use for this type."}, + { LLDB_OPT_SET_3, false, "python-script", 'o', required_argument, NULL, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command."}, + { LLDB_OPT_SET_3, false, "python-function", 'F', required_argument, NULL, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type."}, { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Input Python code to use for this type manually."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', no_argument, NULL, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines."}, { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, @@ -3262,7 +3262,7 @@ CommandObjectTypeSynthAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, - { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypeName, "Use this Python class to produce synthetic children."}, + { LLDB_OPT_SET_2, false, "python-class", 'l', required_argument, NULL, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children."}, { LLDB_OPT_SET_3, false, "input-python", 'P', no_argument, NULL, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } @@ -3548,7 +3548,7 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects."}, { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeNone, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "category", 'w', required_argument, NULL, 0, eArgTypeName, "Add this to the given category instead of the default one."}, - { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeName, "Include this expression path in the synthetic view."}, + { LLDB_OPT_SET_ALL, false, "child", 'c', required_argument, NULL, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeNone, "Type names are actually regular expressions."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; diff --git a/lldb/source/Core/DataExtractor.cpp b/lldb/source/Core/DataExtractor.cpp index d869aaef669..2cfced03800 100644 --- a/lldb/source/Core/DataExtractor.cpp +++ b/lldb/source/Core/DataExtractor.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/MathExtras.h" +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/Log.h" @@ -178,15 +179,6 @@ DataExtractor::Clear () } //------------------------------------------------------------------ -// Returns the total number of bytes that this object refers to -//------------------------------------------------------------------ -size_t -DataExtractor::GetByteSize () const -{ - return m_end - m_start; -} - -//------------------------------------------------------------------ // If this object contains shared data, this function returns the // offset into that shared data. Else zero is returned. //------------------------------------------------------------------ @@ -210,16 +202,6 @@ DataExtractor::GetSharedDataOffset () const } //------------------------------------------------------------------ -// Returns true if OFFSET is a valid offset into the data in this -// object. -//------------------------------------------------------------------ -bool -DataExtractor::ValidOffset (uint32_t offset) const -{ - return offset < GetByteSize(); -} - -//------------------------------------------------------------------ // Returns true if there are LENGTH bytes availabe starting OFFSET // into the data that is in this object. //------------------------------------------------------------------ @@ -245,65 +227,6 @@ DataExtractor::ValidOffsetForDataOfSize (uint32_t offset, uint32_t length) const return ((offset + length) <= size); } -//------------------------------------------------------------------ -// Returns a pointer to the first byte contained in this object's -// data, or NULL of there is no data in this object. -//------------------------------------------------------------------ -const uint8_t * -DataExtractor::GetDataStart () const -{ - return m_start; -} -//------------------------------------------------------------------ -// Returns a pointer to the byte past the last byte contained in -// this object's data, or NULL of there is no data in this object. -//------------------------------------------------------------------ -const uint8_t * -DataExtractor::GetDataEnd () const -{ - return m_end; -} - -//------------------------------------------------------------------ -// Returns true if this object will endian swap values as it -// extracts data. -//------------------------------------------------------------------ -ByteOrder -DataExtractor::GetByteOrder () const -{ - return m_byte_order; -} -//------------------------------------------------------------------ -// Set whether this object will endian swap values as it extracts -// data. -//------------------------------------------------------------------ -void -DataExtractor::SetByteOrder (ByteOrder endian) -{ - m_byte_order = endian; -} - - -//------------------------------------------------------------------ -// Return the size in bytes of any address values this object will -// extract -//------------------------------------------------------------------ -uint8_t -DataExtractor::GetAddressByteSize () const -{ - return m_addr_size; -} - -//------------------------------------------------------------------ -// Set the size in bytes that will be used when extracting any -// address values from data contained in this object. -//------------------------------------------------------------------ -void -DataExtractor::SetAddressByteSize (uint8_t addr_size) -{ - m_addr_size = addr_size; -} - //---------------------------------------------------------------------- // Set the data with which this object will extract from to data // starting at BYTES and set the length of the data to LENGTH bytes @@ -1901,3 +1824,79 @@ DataExtractor::DumpHexBytes (Stream *s, base_addr, // Base address 0, 0); // Bitfield info } + +size_t +DataExtractor::Copy (DataExtractor &dest_data) const +{ + if (m_data_sp.get()) + { + // we can pass along the SP to the data + dest_data.SetData(m_data_sp); + } + else + { + const uint8_t *base_ptr = m_start; + size_t data_size = GetByteSize(); + dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size))); + } + return GetByteSize(); +} + +bool +DataExtractor::Append(DataExtractor& rhs) +{ + if (rhs.GetByteOrder() != GetByteOrder()) + return false; + + if (rhs.GetByteSize() == 0) + return true; + + if (GetByteSize() == 0) + return (rhs.Copy(*this) > 0); + + size_t bytes = GetByteSize() + rhs.GetByteSize(); + + DataBufferHeap *buffer_heap_ptr = NULL; + DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); + + if (buffer_sp.get() == NULL || buffer_heap_ptr == NULL) + return false; + + uint8_t* bytes_ptr = buffer_heap_ptr->GetBytes(); + + memcpy(bytes_ptr, GetDataStart(), GetByteSize()); + memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize()); + + SetData(buffer_sp); + + return true; +} + +bool +DataExtractor::Append(void* buf, uint32_t length) +{ + if (buf == NULL) + return false; + + if (length == 0) + return true; + + size_t bytes = GetByteSize() + length; + + DataBufferHeap *buffer_heap_ptr = NULL; + DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); + + if (buffer_sp.get() == NULL || buffer_heap_ptr == NULL) + return false; + + uint8_t* bytes_ptr = buffer_heap_ptr->GetBytes(); + + if (GetByteSize() > 0) + memcpy(bytes_ptr, GetDataStart(), GetByteSize()); + + memcpy(bytes_ptr + GetByteSize(), buf, length); + + SetData(buffer_sp); + + return true; +}
\ No newline at end of file diff --git a/lldb/source/Core/DataVisualization.cpp b/lldb/source/Core/DataVisualization.cpp index 6974132617a..7c326ed6ec0 100644 --- a/lldb/source/Core/DataVisualization.cpp +++ b/lldb/source/Core/DataVisualization.cpp @@ -106,14 +106,14 @@ DataVisualization::AnyMatches (ConstString type_name, bool DataVisualization::Categories::Get (const ConstString &category, lldb::FormatCategorySP &entry) { - entry = GetFormatManager().Category(category); + entry = GetFormatManager().GetCategory(category); return true; } void DataVisualization::Categories::Add (const ConstString &category) { - GetFormatManager().Category(category); + GetFormatManager().GetCategory(category); } bool @@ -132,13 +132,13 @@ DataVisualization::Categories::Clear () void DataVisualization::Categories::Clear (ConstString &category) { - GetFormatManager().Category(category)->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); + GetFormatManager().GetCategory(category)->Clear(eFormatCategoryItemSummary | eFormatCategoryItemRegexSummary); } void DataVisualization::Categories::Enable (ConstString& category) { - if (GetFormatManager().Category(category)->IsEnabled() == false) + if (GetFormatManager().GetCategory(category)->IsEnabled() == false) GetFormatManager().EnableCategory(category); else { @@ -150,7 +150,7 @@ DataVisualization::Categories::Enable (ConstString& category) void DataVisualization::Categories::Disable (ConstString& category) { - if (GetFormatManager().Category(category)->IsEnabled() == true) + if (GetFormatManager().GetCategory(category)->IsEnabled() == true) GetFormatManager().DisableCategory(category); } diff --git a/lldb/source/Core/FormatClasses.cpp b/lldb/source/Core/FormatClasses.cpp index a23225d3825..ee689307ac1 100644 --- a/lldb/source/Core/FormatClasses.cpp +++ b/lldb/source/Core/FormatClasses.cpp @@ -41,30 +41,6 @@ ValueFormat::ValueFormat (lldb::Format f, { } -std::string -ValueFormat::FormatObject(lldb::ValueObjectSP object) -{ - if (!object.get()) - return "NULL"; - - StreamString sstr; - - if (ClangASTType::DumpTypeValue (object->GetClangAST(), // The clang AST - object->GetClangType(), // The clang type to display - &sstr, - m_format, // Format to display this type with - object->GetDataExtractor(), // Data to extract from - 0, // Byte offset into "data" - object->GetByteSize(), // Byte size of item in "data" - object->GetBitfieldBitSize(), // Bitfield bit size - object->GetBitfieldBitOffset())) // Bitfield bit offset - return (sstr.GetString()); - else - { - return ("unsufficient data for value"); - } -} - SummaryFormat::SummaryFormat(bool casc, bool skipptr, bool skipref, @@ -186,29 +162,8 @@ ScriptSummaryFormat::ScriptSummaryFormat(bool casc, std::string ScriptSummaryFormat::FormatObject(lldb::ValueObjectSP object) { - lldb::ValueObjectSP target_object; - if (object->GetIsExpressionResult() && - ClangASTContext::IsPointerType(object->GetClangType()) && - object->GetValue().GetValueType() == Value::eValueTypeHostAddress) - { - // when using the expression parser, an additional layer of "frozen data" - // can be created, which is basically a byte-exact copy of the data returned - // by the expression, but in host memory. because Python code might need to read - // into the object memory in non-obvious ways, we need to hand it the target version - // of the expression output - lldb::addr_t tgt_address = object->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - target_object = ValueObjectConstResult::Create (object->GetExecutionContextScope(), - object->GetClangAST(), - object->GetClangType(), - object->GetName(), - tgt_address, - eAddressTypeLoad, - object->GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); - } - else - target_object = object; return std::string(ScriptInterpreterPython::CallPythonScriptFunction(m_function_name.c_str(), - target_object).c_str()); + object).c_str()); } std::string @@ -282,25 +237,6 @@ SyntheticScriptProvider::FrontEnd::FrontEnd(std::string pclass, return; } - if (be->GetIsExpressionResult() && - ClangASTContext::IsPointerType(be->GetClangType()) && - be->GetValue().GetValueType() == Value::eValueTypeHostAddress) - { - // when using the expression parser, an additional layer of "frozen data" - // can be created, which is basically a byte-exact copy of the data returned - // by the expression, but in host memory. because Python code might need to read - // into the object memory in non-obvious ways, we need to hand it the target version - // of the expression output - lldb::addr_t tgt_address = be->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - m_backend = ValueObjectConstResult::Create (be->GetExecutionContextScope(), - be->GetClangAST(), - be->GetClangType(), - be->GetName(), - tgt_address, - eAddressTypeLoad, - be->GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); - } - m_interpreter = m_backend->GetUpdatePoint().GetTargetSP()->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); if (m_interpreter == NULL) @@ -315,19 +251,7 @@ SyntheticScriptProvider::FrontEnd::GetChildAtIndex (uint32_t idx, bool can_creat if (m_wrapper == NULL || m_interpreter == NULL) return lldb::ValueObjectSP(); - PyObject* py_return = (PyObject*)m_interpreter->GetChildAtIndex(m_wrapper, idx); - if (py_return == NULL || py_return == Py_None) - { - Py_XDECREF(py_return); - return lldb::ValueObjectSP(); - } - - lldb::SBValue *sb_ptr = m_interpreter->CastPyObjectToSBValue(py_return); - - if (py_return == NULL || sb_ptr == NULL) - return lldb::ValueObjectSP(); - - return sb_ptr->m_opaque_sp; + return m_interpreter->GetChildAtIndex(m_wrapper, idx); } std::string diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 40d3a81da39..f9bb3e1a6e9 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -482,11 +482,11 @@ CategoryMap::LoopThrough(CallbackType callback, void* param) } lldb::FormatCategorySP -FormatManager::Category (const ConstString& category_name, +FormatManager::GetCategory (const ConstString& category_name, bool can_create) { if (!category_name) - return Category(m_default_category_name); + return GetCategory(m_default_category_name); lldb::FormatCategorySP category; if (m_categories_map.Get(category_name, category)) return category; @@ -495,7 +495,7 @@ FormatManager::Category (const ConstString& category_name, return lldb::FormatCategorySP(); m_categories_map.Add(category_name,lldb::FormatCategorySP(new FormatCategory(this, category_name.AsCString()))); - return Category(category_name); + return GetCategory(category_name); } lldb::Format @@ -566,11 +566,13 @@ FormatManager::FormatManager() : lldb::RegularExpressionSP any_size_char_arr(new RegularExpression("char \\[[0-9]+\\]")); - Category(m_system_category_name)->GetSummaryNavigator()->Add(ConstString("char *"), string_format); - Category(m_system_category_name)->GetSummaryNavigator()->Add(ConstString("const char *"), string_format); - Category(m_system_category_name)->GetRegexSummaryNavigator()->Add(any_size_char_arr, string_array_format); + FormatCategory::SharedPointer sys_category_sp = GetCategory(m_system_category_name); - Category(m_default_category_name); // this call is there to force LLDB into creating an empty "default" category + sys_category_sp->GetSummaryNavigator()->Add(ConstString("char *"), string_format); + sys_category_sp->GetSummaryNavigator()->Add(ConstString("const char *"), string_format); + sys_category_sp->GetRegexSummaryNavigator()->Add(any_size_char_arr, string_array_format); + + GetCategory(m_default_category_name); // this call is there to force LLDB into creating an empty "default" category // WARNING: temporary code!! // The platform should be responsible for initializing its own formatters @@ -586,24 +588,27 @@ FormatManager::FormatManager() : true, false, "${var._M_dataplus._M_p}")); - Category(m_gnu_cpp_category_name)->GetSummaryNavigator()->Add(ConstString("std::string"), - std_string_summary_sp); - Category(m_gnu_cpp_category_name)->GetSummaryNavigator()->Add(ConstString("std::basic_string<char>"), - std_string_summary_sp); - Category(m_gnu_cpp_category_name)->GetSummaryNavigator()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), - std_string_summary_sp); - - Category(m_gnu_cpp_category_name)->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("std::vector<")), + + FormatCategory::SharedPointer gnu_category_sp = GetCategory(m_gnu_cpp_category_name); + + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::string"), + std_string_summary_sp); + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char>"), + std_string_summary_sp); + gnu_category_sp->GetSummaryNavigator()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"), + std_string_summary_sp); + + gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?vector<.+>$")), SyntheticChildrenSP(new SyntheticScriptProvider(true, false, false, "gnu_libstdcpp.StdVectorSynthProvider"))); - Category(m_gnu_cpp_category_name)->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("std::map<")), + gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?map<.+> >$")), SyntheticChildrenSP(new SyntheticScriptProvider(true, false, false, "gnu_libstdcpp.StdMapSynthProvider"))); - Category(m_gnu_cpp_category_name)->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("std::list<")), + gnu_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::)?list<.+>$")), SyntheticChildrenSP(new SyntheticScriptProvider(true, false, false, diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 2ab5ac4cbcf..78e18ac9f3d 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -89,14 +89,13 @@ ValueObject::ValueObject (ValueObject &parent) : m_value_did_change (false), m_children_count_valid (false), m_old_value_valid (false), - m_pointers_point_to_load_addrs (false), m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), m_is_child_at_offset(false), - m_is_expression_result(parent.m_is_expression_result), - m_dump_printable_counter(0) + m_dump_printable_counter(0), + m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid) { m_manager->ManageObject(this); } @@ -104,7 +103,8 @@ ValueObject::ValueObject (ValueObject &parent) : //---------------------------------------------------------------------- // ValueObject constructor //---------------------------------------------------------------------- -ValueObject::ValueObject (ExecutionContextScope *exe_scope) : +ValueObject::ValueObject (ExecutionContextScope *exe_scope, + AddressType child_ptr_or_ref_addr_type) : UserID (++g_value_obj_uid), // Unique identifier for every value object m_parent (NULL), m_update_point (exe_scope), @@ -135,14 +135,13 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_value_did_change (false), m_children_count_valid (false), m_old_value_valid (false), - m_pointers_point_to_load_addrs (false), m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), m_is_bitfield_for_scalar(false), m_is_expression_path_child(false), m_is_child_at_offset(false), - m_is_expression_result(false), - m_dump_printable_counter(0) + m_dump_printable_counter(0), + m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type) { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -165,13 +164,24 @@ bool ValueObject::UpdateValueIfNeeded (DynamicValueType use_dynamic, bool update_format) { + bool did_change_formats = false; + if (update_format) - UpdateFormatsIfNeeded(use_dynamic); + did_change_formats = UpdateFormatsIfNeeded(use_dynamic); // If this is a constant value, then our success is predicated on whether // we have an error or not if (GetIsConstant()) + { + // if you were asked to update your formatters, but did not get a chance to do it + // clear your own values (this serves the purpose of faking a stop-id for frozen + // objects (which are regarded as constant, but could have changes behind their backs + // because of the frozen-pointer depth limit) + // TODO: decouple summary from value and then remove this code and only force-clear the summary + if (update_format && !did_change_formats) + m_summary_str.clear(); return m_error.Success(); + } bool first_update = m_update_point.IsFirstEvaluation(); @@ -216,7 +226,7 @@ ValueObject::UpdateValueIfNeeded (DynamicValueType use_dynamic, bool update_form return m_error.Success(); } -void +bool ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) { LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); @@ -225,10 +235,14 @@ ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) GetName().GetCString(), m_last_format_mgr_revision, DataVisualization::GetCurrentRevision()); + + bool any_change = false; + if (HasCustomSummaryFormat() && m_update_point.GetModID() != m_user_id_of_forced_summary) { ClearCustomSummaryFormat(); m_summary_str.clear(); + any_change = true; } if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision()) || m_last_format_mgr_dynamic != use_dynamic) @@ -242,6 +256,7 @@ ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) m_synthetic_value = NULL; + any_change = true; DataVisualization::ValueFormats::Get(*this, eNoDynamicValues, m_last_value_format); DataVisualization::GetSummaryFormat(*this, use_dynamic, m_last_summary_format); DataVisualization::GetSyntheticChildren(*this, use_dynamic, m_last_synthetic_filter); @@ -251,6 +266,9 @@ ValueObject::UpdateFormatsIfNeeded(DynamicValueType use_dynamic) ClearUserVisibleData(); } + + return any_change; + } void @@ -538,10 +556,11 @@ ValueObject::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int3 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent); - if (m_pointers_point_to_load_addrs) - valobj->SetPointersPointToLoadAddrs (m_pointers_point_to_load_addrs); - } + child_is_deref_of_parent, + eAddressTypeInvalid); + //if (valobj) + // valobj->SetAddressTypeOfChildren(eAddressTypeInvalid); + } return valobj; } @@ -578,8 +597,7 @@ ValueObject::GetSummaryAsCString () if (ClangASTContext::IsFunctionPointerType (clang_type)) { AddressType func_ptr_address_type = eAddressTypeInvalid; - addr_t func_ptr_address = GetPointerValue (func_ptr_address_type, true); - + addr_t func_ptr_address = GetPointerValue (&func_ptr_address_type); if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS) { switch (func_ptr_address_type) @@ -643,10 +661,157 @@ ValueObject::IsCStringContainer(bool check_pointer) return true; addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; - cstr_address = GetAddressOf (cstr_address_type, true); + cstr_address = GetAddressOf (true, &cstr_address_type); return (cstr_address != LLDB_INVALID_ADDRESS); } +size_t +ValueObject::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + if (!IsPointerType() && !IsArrayType()) + return 0; + + if (item_count == 0) + return 0; + + uint32_t stride = 0; + + ClangASTType type(GetClangAST(), + GetClangType()); + + const uint64_t item_type_size = (IsPointerType() ? ClangASTType::GetTypeByteSize(GetClangAST(), type.GetPointeeType()) : + ClangASTType::GetTypeByteSize(GetClangAST(), type.GetArrayElementType(stride))); + + const uint64_t bytes = item_count * item_type_size; + + const uint64_t offset = item_idx * item_type_size; + + if (item_idx == 0 && item_count == 1) // simply a deref + { + if (IsPointerType()) + { + Error error; + ValueObjectSP pointee_sp = Dereference(error); + if (error.Fail() || pointee_sp.get() == NULL) + return 0; + return pointee_sp->GetDataExtractor().Copy(data); + } + else + { + ValueObjectSP child_sp = GetChildAtIndex(0, true); + if (child_sp.get() == NULL) + return 0; + return child_sp->GetDataExtractor().Copy(data); + } + return true; + } + else /* (items > 1) */ + { + Error error; + lldb_private::DataBufferHeap* heap_buf_ptr = NULL; + lldb::DataBufferSP data_sp(heap_buf_ptr = new lldb_private::DataBufferHeap()); + + AddressType addr_type; + lldb::addr_t addr = IsPointerType() ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type); + + ExecutionContextScope *exe_scope = m_update_point.GetExecutionContextScope(); + + + switch (addr_type) + { + case eAddressTypeFile: + { + Module* module = GetModule(); + if (module) + { + Address so_addr; + module->ResolveFileAddress(addr, so_addr); + if (exe_scope) + { + Target* target = exe_scope->CalculateTarget(); + if (target) + { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = target->ReadMemory(so_addr, false, heap_buf_ptr->GetBytes(), bytes, error); + if (error.Success()) + { + data.SetData(data_sp); + return bytes_read; + } + } + } + } + } + break; + case eAddressTypeLoad: + if (exe_scope) + { + Process *process = exe_scope->CalculateProcess(); + if (process) + { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = process->ReadMemory(addr + offset, heap_buf_ptr->GetBytes(), bytes, error); + if (error.Success()) + { + data.SetData(data_sp); + return bytes_read; + } + } + } + break; + case eAddressTypeHost: + { + heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes); + data.SetData(data_sp); + return bytes; + } + break; + case eAddressTypeInvalid: + default: + break; + } + } + return 0; +} + +size_t +ValueObject::GetData (DataExtractor& data) +{ + UpdateValueIfNeeded(false); + ExecutionContext exe_ctx; + GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); + Error error = m_value.GetValueAsData(&exe_ctx, GetClangAST(), data, 0, GetModule()); + if (error.Fail()) + return 0; + data.SetAddressByteSize(m_data.GetAddressByteSize()); + data.SetByteOrder(m_data.GetByteOrder()); + return data.GetByteSize(); +} + +// will compute strlen(str), but without consuming more than +// maxlen bytes out of str (this serves the purpose of reading +// chunks of a string without having to worry about +// missing NULL terminators in the chunk) +// of course, if strlen(str) > maxlen, the function will return +// maxlen_value (which should be != maxlen, because that allows you +// to know whether strlen(str) == maxlen or strlen(str) > maxlen) +static uint32_t +strlen_or_inf (const char* str, + uint32_t maxlen, + uint32_t maxlen_value) +{ + uint32_t len = 0; + while(*str) + { + len++;str++; + if (len > maxlen) + return maxlen_value; + } + return len; +} + void ValueObject::ReadPointedString(Stream& s, Error& error, @@ -656,7 +821,7 @@ ValueObject::ReadPointedString(Stream& s, { if (max_length == 0) - max_length = 128; // FIXME this should be a setting, or a formatting parameter + max_length = GetUpdatePoint().GetTargetSP()->GetMaximumSizeOfStringSummary(); clang_type_t clang_type = GetClangType(); clang_type_t elem_or_pointee_clang_type; @@ -690,14 +855,14 @@ ValueObject::ReadPointedString(Stream& s, capped_data = true; cstr_len = max_length; } - cstr_address = GetAddressOf (cstr_address_type, true); + cstr_address = GetAddressOf (true, &cstr_address_type); } else { // We have a pointer - cstr_address = GetPointerValue (cstr_address_type, true); + cstr_address = GetPointerValue (&cstr_address_type); } - if (cstr_address == LLDB_INVALID_ADDRESS) + if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) { s << "<invalid address for data>"; } @@ -706,18 +871,13 @@ ValueObject::ReadPointedString(Stream& s, Address cstr_so_addr (NULL, cstr_address); DataExtractor data; size_t bytes_read = 0; - std::vector<char> data_buffer; - bool prefer_file_cache = false; if (cstr_len > 0 && honor_array) { - data_buffer.resize(cstr_len); - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - cstr_len, - error); - if (bytes_read > 0) + // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host + // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this + GetPointeeData(data, 0, cstr_len); + + if ( (bytes_read = data.GetByteSize()) > 0) { s << '"'; data.Dump (&s, @@ -740,29 +900,31 @@ ValueObject::ReadPointedString(Stream& s, { cstr_len = max_length; const size_t k_max_buf_size = 64; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - s << '"'; + + size_t offset = 0; bool any_data = false; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = target->ReadMemory (cstr_so_addr, - prefer_file_cache, - &data_buffer.front(), - k_max_buf_size, - error)) > 0) + bool finished = false; + // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host + // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this + while ( (bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0 ) { - any_data = true; - size_t len = strlen(&data_buffer.front()); + size_t len = strlen_or_inf(data.PeekCStr(0), k_max_buf_size, k_max_buf_size+1); + if (len > k_max_buf_size) + len = k_max_buf_size; + if (!any_data) + { + s << '"'; + any_data = true; + } if (len == 0) break; if (len > bytes_read) len = bytes_read; if (len > cstr_len) len = cstr_len; + else + finished = true; data.Dump (&s, 0, // Start offset in "data" @@ -776,19 +938,22 @@ ValueObject::ReadPointedString(Stream& s, if (len < k_max_buf_size) break; + if (len >= cstr_len) - { - s << "..."; break; - } + cstr_len -= len; - cstr_so_addr.Slide (k_max_buf_size); + offset += len; } if (any_data == false) s << "<data not available>"; - - s << '"'; + else + { + s << '"'; + if (finished == false) + s << "..."; + } } } } @@ -868,39 +1033,40 @@ ValueObject::GetValueAsCString () case Value::eContextTypeLLDBType: case Value::eContextTypeVariable: { + lldb::Format my_format = GetFormat(); clang_type_t clang_type = GetClangType (); if (clang_type) { - if (m_format == lldb::eFormatDefault && m_last_value_format) - { - m_value_str = m_last_value_format->FormatObject(GetSP()); - } - else + if (m_format == lldb::eFormatDefault) { - StreamString sstr; - Format format = GetFormat(); - if (format == eFormatDefault) - format = (m_is_bitfield_for_scalar ? eFormatUnsigned : - ClangASTType::GetFormat(clang_type)); - - if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST - clang_type, // The clang type to display - &sstr, - format, // Format to display this type with - m_data, // Data to extract from - 0, // Byte offset into "m_data" - GetByteSize(), // Byte size of item in "m_data" - GetBitfieldBitSize(), // Bitfield bit size - GetBitfieldBitOffset())) // Bitfield bit offset - m_value_str.swap(sstr.GetString()); + if (m_last_value_format) + my_format = m_last_value_format->GetFormat(); else { - m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", - m_data.GetByteSize(), - GetByteSize()); - m_value_str.clear(); + if (m_is_bitfield_for_scalar) + my_format = eFormatUnsigned; + else + my_format = ClangASTType::GetFormat(clang_type); } } + StreamString sstr; + if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST + clang_type, // The clang type to display + &sstr, + my_format, // Format to display this type with + m_data, // Data to extract from + 0, // Byte offset into "m_data" + GetByteSize(), // Byte size of item in "m_data" + GetBitfieldBitSize(), // Bitfield bit size + GetBitfieldBitOffset())) // Bitfield bit offset + m_value_str.swap(sstr.GetString()); + else + { + m_error.SetErrorStringWithFormat ("unsufficient data for value (only %u of %u bytes available)", + m_data.GetByteSize(), + GetByteSize()); + m_value_str.clear(); + } } } break; @@ -1218,7 +1384,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, } addr_t -ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address) +ValueObject::GetAddressOf (bool scalar_is_load_address, AddressType *address_type) { if (!UpdateValueIfNeeded(false)) return LLDB_INVALID_ADDRESS; @@ -1228,7 +1394,8 @@ ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_addres case Value::eValueTypeScalar: if (scalar_is_load_address) { - address_type = eAddressTypeLoad; + if(address_type) + *address_type = eAddressTypeLoad; return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); } break; @@ -1237,20 +1404,23 @@ ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_addres case Value::eValueTypeFileAddress: case Value::eValueTypeHostAddress: { - address_type = m_value.GetValueAddressType (); + if(address_type) + *address_type = m_value.GetValueAddressType (); return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); } break; } - address_type = eAddressTypeInvalid; + if (address_type) + *address_type = eAddressTypeInvalid; return LLDB_INVALID_ADDRESS; } addr_t -ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_address) +ValueObject::GetPointerValue (AddressType *address_type) { addr_t address = LLDB_INVALID_ADDRESS; - address_type = eAddressTypeInvalid; + if(address_type) + *address_type = eAddressTypeInvalid; if (!UpdateValueIfNeeded(false)) return address; @@ -1258,28 +1428,21 @@ ValueObject::GetPointerValue (AddressType &address_type, bool scalar_is_load_add switch (m_value.GetValueType()) { case Value::eValueTypeScalar: - if (scalar_is_load_address) - { - address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - address_type = eAddressTypeLoad; - } + address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); break; + case Value::eValueTypeHostAddress: case Value::eValueTypeLoadAddress: case Value::eValueTypeFileAddress: - case Value::eValueTypeHostAddress: { uint32_t data_offset = 0; address = m_data.GetPointer(&data_offset); - address_type = m_value.GetValueAddressType(); - if (address_type == eAddressTypeInvalid) - address_type = eAddressTypeLoad; } break; } - if (m_pointers_point_to_load_addrs) - address_type = eAddressTypeLoad; + if (address_type) + *address_type = GetAddressTypeOfChildren(); return address; } @@ -1553,7 +1716,8 @@ ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_cre to-from+1, from, false, - false); + false, + eAddressTypeInvalid); // Cache the value if we got one back... if (synthetic_child) @@ -1633,7 +1797,8 @@ ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type 0, 0, false, - false); + false, + eAddressTypeInvalid); if (synthetic_child) { AddSyntheticChild(name_const_str, synthetic_child); @@ -2950,7 +3115,7 @@ ValueObject::DumpValueObject // We have a pointer or reference whose value is an address. // Make sure that address is not NULL AddressType ptr_address_type; - if (valobj->GetPointerValue (ptr_address_type, true) == 0) + if (valobj->GetPointerValue (&ptr_address_type) == 0) print_children = false; else if (is_ref && curr_depth == 0) @@ -3084,7 +3249,8 @@ ValueObject::CreateConstantValue (const ConstString &name) ast, GetClangType(), name, - data); + data, + GetAddressOf()); } } @@ -3152,7 +3318,8 @@ ValueObject::Dereference (Error &error) child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, - child_is_deref_of_parent); + child_is_deref_of_parent, + eAddressTypeInvalid); } } @@ -3182,7 +3349,7 @@ ValueObject::AddressOf (Error &error) AddressType address_type = eAddressTypeInvalid; const bool scalar_is_load_address = false; - addr_t addr = GetAddressOf (address_type, scalar_is_load_address); + addr_t addr = GetAddressOf (scalar_is_load_address, &address_type); error.Clear(); if (addr != LLDB_INVALID_ADDRESS) { @@ -3228,8 +3395,7 @@ ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type) { ValueObjectSP valobj_sp; AddressType address_type; - const bool scalar_is_load_address = true; - addr_t ptr_value = GetPointerValue (address_type, scalar_is_load_address); + addr_t ptr_value = GetPointerValue (&address_type); if (ptr_value != LLDB_INVALID_ADDRESS) { @@ -3248,8 +3414,7 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp) { ValueObjectSP valobj_sp; AddressType address_type; - const bool scalar_is_load_address = true; - addr_t ptr_value = GetPointerValue (address_type, scalar_is_load_address); + addr_t ptr_value = GetPointerValue (&address_type); if (ptr_value != LLDB_INVALID_ADDRESS) { @@ -3540,3 +3705,14 @@ ValueObject::ClearUserVisibleData() m_summary_str.clear(); m_object_desc_str.clear(); } + +SymbolContextScope * +ValueObject::GetSymbolContextScope() +{ + if (m_parent) + { + if (!m_parent->IsPointerOrReferenceType()) + return m_parent->GetSymbolContextScope(); + } + return NULL; +} diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp index 4075f60ebb3..b07b38c7544 100644 --- a/lldb/source/Core/ValueObjectChild.cpp +++ b/lldb/source/Core/ValueObjectChild.cpp @@ -35,7 +35,8 @@ ValueObjectChild::ValueObjectChild uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool is_base_class, - bool is_deref_of_parent + bool is_deref_of_parent, + AddressType child_ptr_or_ref_addr_type ) : ValueObject (parent), m_clang_ast (clang_ast), @@ -48,6 +49,7 @@ ValueObjectChild::ValueObjectChild m_is_deref_of_parent (is_deref_of_parent) { m_name = name; + SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); } ValueObjectChild::~ValueObjectChild() @@ -108,10 +110,7 @@ ValueObjectChild::UpdateValue () if (ClangASTContext::IsPointerOrReferenceType (parent->GetClangType())) { - const bool scalar_is_load_address = true; - AddressType address_type; - - lldb::addr_t addr = parent->GetPointerValue (address_type, scalar_is_load_address); + lldb::addr_t addr = parent->GetPointerValue (); m_value.GetScalar() = addr; if (addr == LLDB_INVALID_ADDRESS) @@ -125,10 +124,28 @@ ValueObjectChild::UpdateValue () else { m_value.GetScalar() += m_byte_offset; - if (m_pointers_point_to_load_addrs || - value_type == Value::eValueTypeScalar || - value_type == Value::eValueTypeFileAddress) - m_value.SetValueType (Value::eValueTypeLoadAddress); + AddressType addr_type = parent->GetAddressTypeOfChildren(); + + switch (addr_type) + { + case eAddressTypeFile: + if (m_update_point.GetProcessSP().get() != NULL && m_update_point.GetProcessSP()->IsAlive() == true) + m_value.SetValueType (Value::eValueTypeLoadAddress); + else + m_value.SetValueType(Value::eValueTypeFileAddress); + break; + case eAddressTypeLoad: + m_value.SetValueType (Value::eValueTypeLoadAddress); + break; + case eAddressTypeHost: + m_value.SetValueType(Value::eValueTypeHostAddress); + break; + case eAddressTypeInvalid: + default: + // TODO: does this make sense? + m_value.SetValueType(Value::eValueTypeScalar); + break; + } } } else diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp index 7ceddc99607..9a23ca82a1b 100644 --- a/lldb/source/Core/ValueObjectConstResult.cpp +++ b/lldb/source/Core/ValueObjectConstResult.cpp @@ -9,6 +9,8 @@ #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResultChild.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/ValueObjectList.h" @@ -31,30 +33,34 @@ ValueObjectConstResult::Create ( ExecutionContextScope *exe_scope, ByteOrder byte_order, - uint32_t addr_byte_size + uint32_t addr_byte_size, + lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, byte_order, - addr_byte_size))->GetSP(); + addr_byte_size, + address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult ( ExecutionContextScope *exe_scope, ByteOrder byte_order, - uint32_t addr_byte_size + uint32_t addr_byte_size, + lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (NULL), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { SetIsConstant (); SetValueIsValid(true); m_data.SetByteOrder(byte_order); m_data.SetAddressByteSize(addr_byte_size); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -64,14 +70,16 @@ ValueObjectConstResult::Create clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, - const DataExtractor &data + const DataExtractor &data, + lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, clang_ast, clang_type, name, - data))->GetSP(); + data, + address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult @@ -80,12 +88,14 @@ ValueObjectConstResult::ValueObjectConstResult clang::ASTContext *clang_ast, void *clang_type, const ConstString &name, - const DataExtractor &data + const DataExtractor &data, + lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { m_data = data; m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); @@ -94,7 +104,7 @@ ValueObjectConstResult::ValueObjectConstResult m_name = name; SetIsConstant (); SetValueIsValid(true); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -106,7 +116,8 @@ ValueObjectConstResult::Create const ConstString &name, const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, - uint8_t data_addr_size + uint8_t data_addr_size, + lldb::addr_t address ) { return (new ValueObjectConstResult (exe_scope, @@ -115,7 +126,8 @@ ValueObjectConstResult::Create name, data_sp, data_byte_order, - data_addr_size))->GetSP(); + data_addr_size, + address))->GetSP(); } ValueObjectConstResult::ValueObjectConstResult @@ -126,12 +138,14 @@ ValueObjectConstResult::ValueObjectConstResult const ConstString &name, const lldb::DataBufferSP &data_sp, lldb::ByteOrder data_byte_order, - uint8_t data_addr_size + uint8_t data_addr_size, + lldb::addr_t address ) : ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { m_data.SetByteOrder(data_byte_order); m_data.SetAddressByteSize(data_addr_size); @@ -142,7 +156,7 @@ ValueObjectConstResult::ValueObjectConstResult m_name = name; SetIsConstant (); SetValueIsValid(true); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -179,7 +193,8 @@ ValueObjectConstResult::ValueObjectConstResult ValueObject (exe_scope), m_clang_ast (clang_ast), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this, address) { m_value.GetScalar() = address; m_data.SetAddressByteSize(addr_byte_size); @@ -197,7 +212,7 @@ ValueObjectConstResult::ValueObjectConstResult m_name = name; SetIsConstant (); SetValueIsValid(true); - m_pointers_point_to_load_addrs = true; + SetAddressTypeOfChildren(eAddressTypeLoad); } ValueObjectSP @@ -217,11 +232,11 @@ ValueObjectConstResult::ValueObjectConstResult ( ValueObject (exe_scope), m_clang_ast (NULL), m_type_name (), - m_byte_size (0) + m_byte_size (0), + m_impl(this) { m_error = error; SetIsConstant (); - m_pointers_point_to_load_addrs = true; } ValueObjectConstResult::~ValueObjectConstResult() @@ -244,10 +259,7 @@ size_t ValueObjectConstResult::GetByteSize() { if (m_byte_size == 0) - { - uint64_t bit_width = ClangASTType::GetClangTypeBitWidth (GetClangAST(), GetClangType()); - m_byte_size = (bit_width + 7 ) / 8; - } + m_byte_size = ClangASTType::GetTypeByteSize(GetClangAST(), GetClangType()); return m_byte_size; } @@ -293,3 +305,35 @@ ValueObjectConstResult::IsInScope () // information needed to contain the constant value. return true; } + +lldb::ValueObjectSP +ValueObjectConstResult::Dereference (Error &error) +{ + return m_impl.Dereference(error); +} + +lldb::ValueObjectSP +ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +{ + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); +} + +lldb::ValueObjectSP +ValueObjectConstResult::AddressOf (Error &error) +{ + return m_impl.AddressOf(error); +} + +ValueObject * +ValueObjectConstResult::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) +{ + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, synthetic_index); +} + +size_t +ValueObjectConstResult::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + return m_impl.GetPointeeData(data, item_idx, item_count); +} diff --git a/lldb/source/Core/ValueObjectConstResultChild.cpp b/lldb/source/Core/ValueObjectConstResultChild.cpp new file mode 100644 index 00000000000..2a305a1bea5 --- /dev/null +++ b/lldb/source/Core/ValueObjectConstResultChild.cpp @@ -0,0 +1,82 @@ +//===-- ValueObjectConstResultChild.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ValueObjectConstResultChild.h" + +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectList.h" + +#include "lldb/Symbol/ClangASTContext.h" + +using namespace lldb_private; + +ValueObjectConstResultChild::ValueObjectConstResultChild +( + ValueObject &parent, + clang::ASTContext *clang_ast, + void *clang_type, + const ConstString &name, + uint32_t byte_size, + int32_t byte_offset, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool is_base_class, + bool is_deref_of_parent +) : + ValueObjectChild (parent, + clang_ast, + clang_type, + name, + byte_size, + byte_offset, + bitfield_bit_size, + bitfield_bit_offset, + is_base_class, + is_deref_of_parent, + eAddressTypeLoad), + m_impl(this) +{ + m_name = name; +} + +ValueObjectConstResultChild::~ValueObjectConstResultChild() +{ +} + +lldb::ValueObjectSP +ValueObjectConstResultChild::Dereference (Error &error) +{ + return m_impl.Dereference(error); +} + +lldb::ValueObjectSP +ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create) +{ + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create); +} + +lldb::ValueObjectSP +ValueObjectConstResultChild::AddressOf (Error &error) +{ + return m_impl.AddressOf(error); +} + +ValueObject * +ValueObjectConstResultChild::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) +{ + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, synthetic_index); +} + +size_t +ValueObjectConstResultChild::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + return m_impl.GetPointeeData(data, item_idx, item_count); +} diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp new file mode 100644 index 00000000000..119ba015590 --- /dev/null +++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp @@ -0,0 +1,221 @@ +//===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/ValueObjectConstResultImpl.h" + +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectConstResultChild.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ValueObjectList.h" + +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/Variable.h" + +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +// this macro enables a simpler implementation for some method calls in this object that relies only upon +// ValueObject knowning how to set the address type of its children correctly. the alternative implementation +// relies on being able to create a target copy of the frozen object, which makes it less bug-prone but less +// efficient as well. once we are confident the faster implementation is bug-free, this macro (and the slower +// implementations) can go +#define TRIVIAL_IMPL 1 + +ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj, + lldb::addr_t live_address) : + m_impl_backend(valobj), + m_live_address(live_address), + m_load_addr_backend(), + m_address_of_backend() +{ +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::DerefOnTarget() +{ + if (m_load_addr_backend.get() == NULL) + { + lldb::addr_t tgt_address = m_impl_backend->GetPointerValue(); + m_load_addr_backend = ValueObjectConstResult::Create (m_impl_backend->GetExecutionContextScope(), + m_impl_backend->GetClangAST(), + m_impl_backend->GetClangType(), + m_impl_backend->GetName(), + tgt_address, + eAddressTypeLoad, + m_impl_backend->GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); + } + return m_load_addr_backend; +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::Dereference (Error &error) +{ + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + +#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 + return m_impl_backend->ValueObject::Dereference(error); +#else + m_impl_backend->UpdateValueIfNeeded(false); + + if (NeedsDerefOnTarget()) + return DerefOnTarget()->Dereference(error); + else + return m_impl_backend->ValueObject::Dereference(error); +#endif +} + +ValueObject * +ValueObjectConstResultImpl::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index) +{ + if (m_impl_backend == NULL) + return NULL; + + m_impl_backend->UpdateValueIfNeeded(false); + + ValueObjectConstResultChild *valobj = NULL; + + bool omit_empty_base_classes = true; + bool ignore_array_bounds = synthetic_array_member; + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + + const bool transparent_pointers = synthetic_array_member == false; + clang::ASTContext *clang_ast = m_impl_backend->GetClangAST(); + lldb::clang_type_t clang_type = m_impl_backend->GetClangType(); + lldb::clang_type_t child_clang_type; + + ExecutionContext exe_ctx; + m_impl_backend->GetExecutionContextScope()->CalculateExecutionContext (exe_ctx); + + child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx, + clang_ast, + m_impl_backend->GetName().GetCString(), + clang_type, + idx, + transparent_pointers, + omit_empty_base_classes, + ignore_array_bounds, + child_name_str, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + if (child_clang_type && child_byte_size) + { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString (child_name_str.c_str()); + + valobj = new ValueObjectConstResultChild (*m_impl_backend, + clang_ast, + child_clang_type, + child_name, + child_byte_size, + child_byte_offset, + child_bitfield_bit_size, + child_bitfield_bit_offset, + child_is_base_class, + child_is_deref_of_parent); + valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset); + } + + return valobj; +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create) +{ + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + +#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 + return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create); +#else + m_impl_backend->UpdateValueIfNeeded(false); + + if (NeedsDerefOnTarget()) + return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create); + else + return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create); +#endif +} + +lldb::ValueObjectSP +ValueObjectConstResultImpl::AddressOf (Error &error) +{ + if (m_address_of_backend.get() != NULL) + return m_address_of_backend; + + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + if (m_live_address != LLDB_INVALID_ADDRESS) + { + ClangASTType type(m_impl_backend->GetClangAST(), m_impl_backend->GetClangType()); + + lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t))); + + std::string new_name("&"); + new_name.append(m_impl_backend->GetName().AsCString("")); + + m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetUpdatePoint().GetExecutionContextScope(), + type.GetASTContext(), + type.GetPointerType(), + ConstString(new_name.c_str()), + buffer, + lldb::endian::InlHostByteOrder(), + m_impl_backend->GetExecutionContextScope()->CalculateProcess()->GetAddressByteSize()); + + m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar); + m_address_of_backend->GetValue().GetScalar() = m_live_address; + + return m_address_of_backend; + } + else + return lldb::ValueObjectSP(); +} + +size_t +ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data, + uint32_t item_idx, + uint32_t item_count) +{ + if (m_impl_backend == NULL) + return 0; +#if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1 + return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); +#else + m_impl_backend->UpdateValueIfNeeded(false); + + if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType()) + return DerefOnTarget()->GetPointeeData(data, item_idx, item_count); + else + return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); +#endif +} diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp index 2b381d7cb6b..5717406ba20 100644 --- a/lldb/source/Core/ValueObjectVariable.cpp +++ b/lldb/source/Core/ValueObjectVariable.cpp @@ -145,6 +145,23 @@ ValueObjectVariable::UpdateValue () m_value.SetContext(Value::eContextTypeVariable, variable); Value::ValueType value_type = m_value.GetValueType(); + + switch (value_type) + { + case Value::eValueTypeFileAddress: + SetAddressTypeOfChildren(eAddressTypeFile); + break; + case Value::eValueTypeHostAddress: + SetAddressTypeOfChildren(eAddressTypeHost); + break; + case Value::eValueTypeLoadAddress: + SetAddressTypeOfChildren(eAddressTypeLoad); + break; + case Value::eValueTypeScalar: + // TODO: is this the right thing to do? + SetAddressTypeOfChildren(eAddressTypeInvalid); + break; + } switch (value_type) { @@ -250,4 +267,10 @@ ValueObjectVariable::GetModule() return NULL; } - +SymbolContextScope * +ValueObjectVariable::GetSymbolContextScope() +{ + if (m_variable_sp) + return m_variable_sp->GetSymbolContextScope(); + return NULL; +} diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 1607d8e11c2..b1eafd5e30f 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -697,8 +697,8 @@ SummaryStringHelpTextCallback() "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n" "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type" " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be" - " ${var.x.y}). In expression paths you can use either . or -> without any difference in meaning. You can also use ${*var followed by an expression path and in that case" - " the object referred by the path will be dereferenced before being displayed. If the object is not a pointer, doing so will cause an error.\n" + " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed." + " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n" "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed." "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression" " path refers to:\n" @@ -706,7 +706,41 @@ SummaryStringHelpTextCallback() " and displayed as an individual variable\n" " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are" " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n" - "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1."; + "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n" + "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the" + " special symbols only allowed as part of a variable:\n" + " %V: show the value of the object by default\n" + " %S: show the summary of the object by default\n" + " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n" + " %L: show the location of the object (memory address or a register name)\n" + " %#: show the number of children of the object\n" + " %T: show the type of the object\n" + "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses" + " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would" + " count the number of actual elements stored in an std::list:\n" + "type summary add -s \"${svar%#}\" -x \"std::list<\""; +} + +static const char * +ExprPathHelpTextCallback() +{ + return + "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n" + "For instance, given a class:\n" + " class foo {\n" + " int a;\n" + " int b; .\n" + " foo* next;\n" + " };\n" + "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n" + "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n" + "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n" + "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n" + "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n" + "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract" + " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index" + " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the" + " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory)."; } const char * @@ -742,6 +776,7 @@ CommandObject::g_arguments_data[] = { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL }, { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." }, { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL }, @@ -764,6 +799,9 @@ CommandObject::g_arguments_data[] = { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." }, { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." }, + { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." }, + { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." }, + { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." }, { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." }, { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." }, { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." }, diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index 0f508de7c5d..bbaa8b9ad06 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -18,9 +18,7 @@ #include <string> -#include "lldb/API/SBFrame.h" -#include "lldb/API/SBBreakpointLocation.h" -#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Timer.h" @@ -90,6 +88,36 @@ ReleasePythonLock () PythonMutexPredicate().SetValue (LLDB_INVALID_THREAD_ID, eBroadcastAlways); } +ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *pi, + FILE* tmp_fh, + bool ns) : + m_need_session(ns), + m_release_lock(false), + m_python_interpreter(pi), + m_tmp_fh(tmp_fh) +{ + // if Enter/LeaveSession() must be called, then m_python_interpreter must be != NULL + assert(m_need_session && m_python_interpreter); + if (!CurrentThreadHasPythonLock()) + { + while (!GetPythonLock (1)) + if (tmp_fh) + fprintf (tmp_fh, + "Python interpreter locked on another thread; waiting to acquire lock...\n"); + m_release_lock = true; + } + if (m_need_session) + m_python_interpreter->EnterSession (); +} + +ScriptInterpreterPython::Locker::~Locker() +{ + if (m_need_session) + m_python_interpreter->LeaveSession (); + if (m_release_lock) + ReleasePythonLock (); +} + ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) : ScriptInterpreter (interpreter, eScriptLanguagePython), m_embedded_python_pty (), @@ -226,21 +254,10 @@ ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh) m_dbg_stdout = fh; FILE *tmp_fh = (m_dbg_stdout ? m_dbg_stdout : stdout); - if (!CurrentThreadHasPythonLock ()) - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, "Python interpreter locked on another thread; waiting to acquire lock...\n"); - EnterSession (); - m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); - LeaveSession (); - ReleasePythonLock (); - } - else - { - EnterSession (); - m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); - LeaveSession (); - } + + Locker py_lock(this, tmp_fh); + + m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush); } void @@ -1400,25 +1417,12 @@ ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name void* ret_val; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) + { - python_interpreter->EnterSession (); + Locker py_lock(this, tmp_fh); ret_val = g_swig_synthetic_script (class_name, python_interpreter->m_dictionary_name.c_str(), valobj); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_synthetic_script (class_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; @@ -1526,25 +1530,12 @@ ScriptInterpreterPython::CallPythonScriptFunction (const char *python_function_n && *python_function_name) { FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) + { - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_typescript_callback (python_function_name, python_interpreter->m_dictionary_name.c_str(), valobj); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_typescript_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - valobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } } else @@ -1595,27 +1586,13 @@ ScriptInterpreterPython::BreakpointCallbackFunction { bool ret_val = true; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_breakpoint_callback (python_function_name, - python_interpreter->m_dictionary_name.c_str(), - stop_frame_sp, - bp_loc_sp); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_breakpoint_callback (python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, bp_loc_sp); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; } @@ -1758,55 +1735,47 @@ ScriptInterpreterPython::CalculateNumChildren (void *implementor) uint32_t ret_val = 0; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_calc_children (implementor); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_calc_children (implementor); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; } -void* +lldb::ValueObjectSP ScriptInterpreterPython::GetChildAtIndex (void *implementor, uint32_t idx) { if (!implementor) - return 0; + return lldb::ValueObjectSP(); - if (!g_swig_get_child_index) - return 0; + if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue) + return lldb::ValueObjectSP(); ScriptInterpreterPython *python_interpreter = this; - void* ret_val = NULL; + void* child_ptr = NULL; + lldb::SBValue* value_sb = NULL; + lldb::ValueObjectSP ret_val; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_get_child_index (implementor,idx); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_get_child_index (implementor,idx); - python_interpreter->LeaveSession (); - ReleasePythonLock (); + Locker py_lock(python_interpreter, tmp_fh); + child_ptr = g_swig_get_child_index (implementor,idx); + if (child_ptr != NULL && child_ptr != Py_None) + { + value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr); + if (value_sb == NULL) + Py_XDECREF(child_ptr); + else + ret_val = value_sb->get_sp(); + } + else + { + Py_XDECREF(child_ptr); + } } return ret_val; @@ -1826,21 +1795,10 @@ ScriptInterpreterPython::GetIndexOfChildWithName (void *implementor, const char* int ret_val = UINT32_MAX; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_get_index_child (implementor, child_name); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_get_index_child (implementor, child_name); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return ret_val; @@ -1858,60 +1816,15 @@ ScriptInterpreterPython::UpdateSynthProviderInstance (void* implementor) ScriptInterpreterPython *python_interpreter = this; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - g_swig_update_provider (implementor); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); g_swig_update_provider (implementor); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } return; } -lldb::SBValue* -ScriptInterpreterPython::CastPyObjectToSBValue (void* data) -{ - if (!data) - return NULL; - - if (!g_swig_cast_to_sbvalue) - return NULL; - - ScriptInterpreterPython *python_interpreter = this; - - lldb::SBValue* ret_val = NULL; - - FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_cast_to_sbvalue (data); - python_interpreter->LeaveSession (); - } - else - { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); - ret_val = g_swig_cast_to_sbvalue (data); - python_interpreter->LeaveSession (); - ReleasePythonLock (); - } - - return ret_val; -} - bool ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, const char* args, @@ -1939,31 +1852,15 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, std::string err_msg; FILE *tmp_fh = (python_interpreter->m_dbg_stdout ? python_interpreter->m_dbg_stdout : stdout); - if (CurrentThreadHasPythonLock()) - { - python_interpreter->EnterSession (); - ret_val = g_swig_call_command (impl_function, - python_interpreter->m_dictionary_name.c_str(), - debugger_sp, - args, - err_msg, - cmd_retobj); - python_interpreter->LeaveSession (); - } - else + { - while (!GetPythonLock (1)) - fprintf (tmp_fh, - "Python interpreter locked on another thread; waiting to acquire lock...\n"); - python_interpreter->EnterSession (); + Locker py_lock(python_interpreter, tmp_fh); ret_val = g_swig_call_command (impl_function, python_interpreter->m_dictionary_name.c_str(), debugger_sp, args, err_msg, cmd_retobj); - python_interpreter->LeaveSession (); - ReleasePythonLock (); } if (!ret_val) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 52e07ce4fe7..90b17d1c084 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -62,7 +62,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, // First job, pull out the address at 0 offset from the object. AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(address_type, true); + lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); if (original_ptr == LLDB_INVALID_ADDRESS) return false; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 5c84f710b72..1dfb3645473 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -49,17 +49,11 @@ AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &object) return NULL; // Make the argument list: we pass one arg, the address of our pointer, to the print function. - Scalar scalar; + Value val; - if (!ClangASTType::GetValueAsScalar (object.GetClangAST(), - object.GetClangType(), - object.GetDataExtractor(), - 0, - object.GetByteSize(), - scalar)) + if (!object.ResolveValue(val.GetScalar())) return NULL; - Value val(scalar); return GetObjectDescription(str, val, object.GetExecutionContextScope()); } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 9e97f3b9923..4d4d4fbebf5 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -245,7 +245,7 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, { // First job, pull out the address at 0 offset from the object That will be the ISA pointer. AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(address_type, true); + lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); // ObjC only has single inheritance, so the objects all start at the same pointer value. address.SetSection (NULL); @@ -584,26 +584,6 @@ AppleObjCRuntimeV2::IsTaggedPointer(lldb::addr_t ptr) lldb_private::ObjCLanguageRuntime::ObjCISA AppleObjCRuntimeV2::GetISA(ValueObject& valobj) { - - if (valobj.GetIsExpressionResult() && - valobj.GetValue().GetValueType() == Value::eValueTypeHostAddress) - { - // when using the expression parser, an additional layer of "frozen data" - // can be created, which is basically a byte-exact copy of the data returned - // by the expression, but in host memory. because this code reads memory without - // taking the debug-info-provided object layout, we need to hand it the target version - // of the expression output - lldb::addr_t tgt_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - ValueObjectSP target_object = ValueObjectConstResult::Create (valobj.GetExecutionContextScope(), - valobj.GetClangAST(), - valobj.GetClangType(), - valobj.GetName(), - tgt_address, - eAddressTypeLoad, - valobj.GetUpdatePoint().GetProcessSP()->GetAddressByteSize()); - return GetISA(*target_object); - } - if (ClangASTType::GetMinimumLanguage(valobj.GetClangAST(),valobj.GetClangType()) != lldb::eLanguageTypeObjC) return 0; @@ -613,8 +593,7 @@ AppleObjCRuntimeV2::GetISA(ValueObject& valobj) if (valobj.GetValue().GetContextType() == Value::eContextTypeInvalid) return 0; - uint32_t offset = 0; - uint64_t isa_pointer = valobj.GetDataExtractor().GetPointer(&offset); + lldb::addr_t isa_pointer = valobj.GetPointerValue(); // tagged pointer if (IsTaggedPointer(isa_pointer)) diff --git a/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp b/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp index 2fdd3b099b3..c5f3e40bd34 100644 --- a/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp +++ b/lldb/source/Plugins/OperatingSystem/Darwin-Kernel/OperatingSystemDarwinKernel.cpp @@ -156,9 +156,9 @@ OperatingSystemDarwinKernel::GetDynamicRegisterInfo () ValueObjectSP gpr_valobj_sp (m_thread_list_valobj_sp->GetChildMemberWithName(GetThreadGPRMemberName (), can_create)); if (gpr_valobj_sp->IsPointerType ()) - base_addr = gpr_valobj_sp->GetPointerValue (addr_type, true); + base_addr = gpr_valobj_sp->GetPointerValue (&addr_type); else - base_addr = gpr_valobj_sp->GetAddressOf (addr_type, true); + base_addr = gpr_valobj_sp->GetAddressOf (true, &addr_type); ValueObjectSP child_valobj_sp; if (gpr_valobj_sp) @@ -188,7 +188,7 @@ OperatingSystemDarwinKernel::GetDynamicRegisterInfo () { // Adjust the byte size and the offset to match the layout of registers in our struct reg_info.byte_size = child_valobj_sp->GetByteSize(); - reg_info.byte_offset = child_valobj_sp->GetAddressOf(addr_type, true) - base_addr; + reg_info.byte_offset = child_valobj_sp->GetAddressOf(true, &addr_type) - base_addr; reg_info.kinds[eRegisterKindLLDB] = reg_num++; m_register_info_ap->AddRegister (reg_info, reg_name, empty_name, gpr_name); } @@ -290,9 +290,9 @@ OperatingSystemDarwinKernel::CreateRegisterContextForThread (Thread *thread) if (gpr_valobj_sp) { if (gpr_valobj_sp->IsPointerType ()) - base_addr = gpr_valobj_sp->GetPointerValue (addr_type, true); + base_addr = gpr_valobj_sp->GetPointerValue (&addr_type); else - base_addr = gpr_valobj_sp->GetAddressOf (addr_type, true); + base_addr = gpr_valobj_sp->GetAddressOf (true, &addr_type); reg_ctx_sp.reset (new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), base_addr)); } } diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index b94692bf004..931bd5e7273 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -154,6 +154,53 @@ ClangASTType::GetPointeeType (clang_type_t clang_type) return NULL; } +lldb::clang_type_t +ClangASTType::GetArrayElementType (uint32_t& stride) +{ + return GetArrayElementType(m_ast, m_type, stride); +} + +lldb::clang_type_t +ClangASTType::GetArrayElementType (clang::ASTContext* ast, + lldb::clang_type_t opaque_clang_qual_type, + uint32_t& stride) +{ + if (opaque_clang_qual_type) + { + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)); + + lldb::clang_type_t ret_type = qual_type.getTypePtr()->getArrayElementTypeNoTypeQual()->getCanonicalTypeUnqualified().getAsOpaquePtr(); + + // TODO: the real stride will be >= this value.. find the real one! + stride = GetTypeByteSize(ast, ret_type); + + return ret_type; + + } + return NULL; + +} + +lldb::clang_type_t +ClangASTType::GetPointerType () +{ + return GetPointerType (m_ast, + m_type); +} + +lldb::clang_type_t +ClangASTType::GetPointerType (clang::ASTContext *ast_context, + lldb::clang_type_t opaque_clang_qual_type) +{ + if (opaque_clang_qual_type) + { + clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_clang_qual_type)); + + return ast_context->getPointerType(qual_type).getAsOpaquePtr(); + } + return NULL; +} + lldb::Encoding ClangASTType::GetEncoding (uint32_t &count) { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 25d37435ff6..812d906dbf4 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -623,10 +623,20 @@ Target::ReadMemoryFromFileCache (const Address& addr, void *dst, size_t dst_len, } size_t -Target::ReadMemory (const Address& addr, bool prefer_file_cache, void *dst, size_t dst_len, Error &error) +Target::ReadMemory (const Address& addr, + bool prefer_file_cache, + void *dst, + size_t dst_len, + Error &error, + lldb::addr_t *load_addr_ptr) { error.Clear(); + // if we end up reading this from process memory, we will fill this + // with the actual load address + if (load_addr_ptr) + *load_addr_ptr = LLDB_INVALID_ADDRESS; + bool process_is_valid = m_process_sp && m_process_sp->IsAlive(); size_t bytes_read = 0; @@ -692,7 +702,11 @@ Target::ReadMemory (const Address& addr, bool prefer_file_cache, void *dst, size } } if (bytes_read) + { + if (load_addr_ptr) + *load_addr_ptr = load_addr; return bytes_read; + } // If the address is not section offset we have an address that // doesn't resolve to any address in any currently loaded shared // libaries and we failed to read memory so there isn't anything @@ -1579,6 +1593,7 @@ Target::SettingsController::CreateInstanceSettings (const char *instance_name) #define TSC_SKIP_PROLOGUE "skip-prologue" #define TSC_SOURCE_MAP "source-map" #define TSC_MAX_CHILDREN "max-children-count" +#define TSC_MAX_STRLENSUMMARY "max-string-summary-length" static const ConstString & @@ -1623,6 +1638,12 @@ GetSettingNameForMaxChildren () return g_const_string; } +static const ConstString & +GetSettingNameForMaxStringSummaryLength () +{ + static ConstString g_const_string (TSC_MAX_STRLENSUMMARY); + return g_const_string; +} bool Target::SettingsController::SetGlobalVariable (const ConstString &var_name, @@ -1676,7 +1697,8 @@ TargetInstanceSettings::TargetInstanceSettings m_prefer_dynamic_value (2), m_skip_prologue (true, true), m_source_map (NULL, NULL), - m_max_children_display(256) + m_max_children_display(256), + m_max_strlen_length(1024) { // CopyInstanceSettings is a pure virtual function in InstanceSettings; it therefore cannot be called // until the vtables for TargetInstanceSettings are properly set up, i.e. AFTER all the initializers. @@ -1703,7 +1725,8 @@ TargetInstanceSettings::TargetInstanceSettings (const TargetInstanceSettings &rh m_prefer_dynamic_value (rhs.m_prefer_dynamic_value), m_skip_prologue (rhs.m_skip_prologue), m_source_map (rhs.m_source_map), - m_max_children_display(rhs.m_max_children_display) + m_max_children_display(rhs.m_max_children_display), + m_max_strlen_length(rhs.m_max_strlen_length) { if (m_instance_name != InstanceSettings::GetDefaultName()) { @@ -1787,6 +1810,13 @@ TargetInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_n if (ok) m_max_children_display = new_value; } + else if (var_name == GetSettingNameForMaxStringSummaryLength()) + { + bool ok; + uint32_t new_value = Args::StringToUInt32(value, 0, 10, &ok); + if (ok) + m_max_strlen_length = new_value; + } else if (var_name == GetSettingNameForSourcePathMap ()) { switch (op) @@ -1858,6 +1888,7 @@ TargetInstanceSettings::CopyInstanceSettings (const lldb::InstanceSettingsSP &ne m_prefer_dynamic_value = new_settings_ptr->m_prefer_dynamic_value; m_skip_prologue = new_settings_ptr->m_skip_prologue; m_max_children_display = new_settings_ptr->m_max_children_display; + m_max_strlen_length = new_settings_ptr->m_max_strlen_length; } bool @@ -1893,6 +1924,12 @@ TargetInstanceSettings::GetInstanceSettingsValue (const SettingEntry &entry, count_str.Printf ("%d", m_max_children_display); value.AppendString (count_str.GetData()); } + else if (var_name == GetSettingNameForMaxStringSummaryLength()) + { + StreamString count_str; + count_str.Printf ("%d", m_max_strlen_length); + value.AppendString (count_str.GetData()); + } else { if (err) @@ -1940,12 +1977,13 @@ Target::SettingsController::global_settings_table[] = SettingEntry Target::SettingsController::instance_settings_table[] = { - // var-name var-type default enum init'd hidden help-text - // ================= ================== =============== ======================= ====== ====== ========================================================================= - { TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." }, - { TSC_PREFER_DYNAMIC, eSetVarTypeEnum , NULL , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." }, - { TSC_SKIP_PROLOGUE , eSetVarTypeBoolean, "true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." }, - { TSC_SOURCE_MAP , eSetVarTypeArray , NULL , NULL, false, false, "Source path remappings to use when locating source files from debug information." }, - { TSC_MAX_CHILDREN , eSetVarTypeInt , "256" , NULL, true, false, "Maximum number of children to expand in any level of depth." }, - { NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL } + // var-name var-type default enum init'd hidden help-text + // ================= ================== =============== ======================= ====== ====== ========================================================================= + { TSC_EXPR_PREFIX , eSetVarTypeString , NULL , NULL, false, false, "Path to a file containing expressions to be prepended to all expressions." }, + { TSC_PREFER_DYNAMIC , eSetVarTypeEnum , NULL , g_dynamic_value_types, false, false, "Should printed values be shown as their dynamic value." }, + { TSC_SKIP_PROLOGUE , eSetVarTypeBoolean, "true" , NULL, false, false, "Skip function prologues when setting breakpoints by name." }, + { TSC_SOURCE_MAP , eSetVarTypeArray , NULL , NULL, false, false, "Source path remappings to use when locating source files from debug information." }, + { TSC_MAX_CHILDREN , eSetVarTypeInt , "256" , NULL, true, false, "Maximum number of children to expand in any level of depth." }, + { TSC_MAX_STRLENSUMMARY , eSetVarTypeInt , "1024" , NULL, true, false, "Maximum number of characters to show when using %s in summary strings." }, + { NULL , eSetVarTypeNone , NULL , NULL, false, false, NULL } }; diff --git a/lldb/test/expression_command/formatters/Makefile b/lldb/test/expression_command/formatters/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/test/expression_command/formatters/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/expression_command/formatters/TestFormatters.py b/lldb/test/expression_command/formatters/TestFormatters.py new file mode 100644 index 00000000000..027191b681e --- /dev/null +++ b/lldb/test/expression_command/formatters/TestFormatters.py @@ -0,0 +1,175 @@ +""" +Test using LLDB data formatters with frozen objects coming from the expression parser. +""" + +import unittest2 +import lldb +import lldbutil +from lldbtest import * + +class ExprFormattersTestCase(TestBase): + + mydir = os.path.join("expression_command", "formatters") + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.cpp. + self.line = line_number('main.cpp', + '// Stop here') + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_with_dsym(self): + """Test expr + formatters for good interoperability.""" + self.buildDsym() + self.do_my_test() + + def test_with_dwarf_(self): + """Test expr + formatters for good interoperability.""" + self.buildDsym() + self.do_my_test() + + def do_my_test(self): + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type summary clear', check=False) + self.runCmd('type synthetic clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + """Test expr + formatters for good interoperability.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + self.runCmd("script import formatters") + self.runCmd("script import foosynth") + + self.runCmd("frame variable foo1 -T") + self.runCmd("frame variable foo1.b -T") + self.runCmd("frame variable foo1.b.b_ref -T") + + self.expect("p *(new foo(47))", + substrs = ['(int) a = 47', '(bar) b = {', '(int) i = 94', '(baz) b = {', '(int) k = 99']) + + self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") + + self.expect("p new int(12)", + substrs = ['(int *) $', ' = 0x']) + + self.runCmd("type summary add -s \"${var%pointer} -> ${*var%decimal}\" \"int *\"") + + self.expect("p new int(12)", + substrs = ['(int *) $', '= 0x', ' -> 12']) + + self.expect("p foo1.a_ptr", + substrs = ['(int *) $', '= 0x', ' -> 13']) + + self.expect("p foo1", + substrs = ['(foo) $', ' = a = 12, a_ptr = ', ' -> 13, i = 24, i_ptr = ', ' -> 25']) + + self.expect("p new foo(47)", + substrs = ['(foo *) $', ' a = 47, a_ptr = ', ' -> 48, i = 94, i_ptr = ', ' -> 95']) + + self.expect("p foo2", + substrs = ['(foo) $', ' = a = 121, a_ptr = ', ' -> 122, i = 242, i_ptr = ', ' -> 243']) + + object_name = self.res.GetOutput() + object_name = object_name[7:] + object_name = object_name[0:object_name.find(' =')] + + self.expect("frame variable foo2", + substrs = ['(foo)', 'foo2', ' = a = 121, a_ptr = ', ' -> 122, i = 242, i_ptr = ', ' -> 243']) + + self.expect("p $" + object_name, + substrs = ['(foo) $', ' = a = 121, a_ptr = ', ' -> 122, i = 242, i_ptr = ', ' -> 243', ', h = 245 , k = 247']) + + self.runCmd("type summary delete foo") + self.runCmd("type synthetic add --python-class foosynth.FooSyntheticProvider foo") + + self.expect("p $" + object_name, + substrs = ['(foo) $', ' = {', '(int) *i_ptr = 243']) + + self.runCmd("n") + self.runCmd("n") + + self.runCmd("type synthetic delete foo") + self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") + + self.expect("p foo2", + substrs = ['(foo) $', ' = a = 7777, a_ptr = ', ' -> 122, i = 242, i_ptr = ', ' -> 8888']) + + self.expect("p $" + object_name + '.a', + substrs = ['7777']) + + self.expect("p *$" + object_name + '.b.i_ptr', + substrs = ['8888']) + + self.expect("p $" + object_name, + substrs = ['(foo) $', ' = a = 121, a_ptr = ', ' -> 122, i = 242, i_ptr = ', ' -> 8888', 'h = 245 , k = 247']) + + self.runCmd("type summary delete foo") + self.runCmd("type synthetic add --python-class foosynth.FooSyntheticProvider foo") + + self.expect("p $" + object_name, + substrs = ['(foo) $', ' = {', '(int) *i_ptr = 8888']) + + self.runCmd("n") + + self.runCmd("type synthetic delete foo") + self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") + + self.expect("p $" + object_name, + substrs = ['(foo) $', ' = a = 121, a_ptr = ', ' -> 122, i = 242, i_ptr = ', ' -> 8888', 'h = 9999 , k = 247']) + + process = self.dbg.GetSelectedTarget().GetProcess() + thread = process.GetThreadAtIndex(0) + frame = thread.GetSelectedFrame() + + frozen = frame.EvaluateExpression("$" + object_name + ".a_ptr") + + a_data = frozen.GetPointeeData() + + error = lldb.SBError() + self.assertTrue(a_data.GetUnsignedInt32(error, 0) == 122, '*a_ptr = 122') + + self.runCmd("n");self.runCmd("n");self.runCmd("n"); + + self.expect("frame variable numbers", + substrs = ['1','2','3','4','5']) + + self.expect("p numbers", + substrs = ['1','2','3','4','5']) + + frozen = frame.EvaluateExpression("&numbers") + + a_data = frozen.GetPointeeData(0, 1) + + self.assertTrue(a_data.GetUnsignedInt32(error, 0) == 1, 'numbers[0] == 1') + self.assertTrue(a_data.GetUnsignedInt32(error, 4) == 2, 'numbers[1] == 2') + self.assertTrue(a_data.GetUnsignedInt32(error, 8) == 3, 'numbers[2] == 3') + self.assertTrue(a_data.GetUnsignedInt32(error, 12) == 4, 'numbers[3] == 4') + self.assertTrue(a_data.GetUnsignedInt32(error, 16) == 5, 'numbers[4] == 5') + + frozen = frame.EvaluateExpression("numbers") + + a_data = frozen.GetData() + + self.assertTrue(a_data.GetUnsignedInt32(error, 0) == 1, 'numbers[0] == 1') + self.assertTrue(a_data.GetUnsignedInt32(error, 4) == 2, 'numbers[1] == 2') + self.assertTrue(a_data.GetUnsignedInt32(error, 8) == 3, 'numbers[2] == 3') + self.assertTrue(a_data.GetUnsignedInt32(error, 12) == 4, 'numbers[3] == 4') + self.assertTrue(a_data.GetUnsignedInt32(error, 16) == 5, 'numbers[4] == 5') + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/expression_command/formatters/foosynth.py b/lldb/test/expression_command/formatters/foosynth.py new file mode 100644 index 00000000000..91c4d4a84c6 --- /dev/null +++ b/lldb/test/expression_command/formatters/foosynth.py @@ -0,0 +1,29 @@ +import lldb + +class FooSyntheticProvider: + def __init__(self,valobj,dict): + self.valobj = valobj; + self.update(); + + def update(self): + self.adjust_for_architecture() + + def num_children(self): + return 1; + + def get_child_at_index(self,index): + if index != 0: + return None; + return self.i_ptr.Dereference(); + + def get_child_index(self,name): + if name == "*i_ptr": + return 0; + return None; + + def adjust_for_architecture(self): + self.lp64 = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8) + self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle) + self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize() + self.bar = self.valobj.GetChildMemberWithName('b'); + self.i_ptr = self.bar.GetChildMemberWithName('i_ptr');
\ No newline at end of file diff --git a/lldb/test/expression_command/formatters/formatters.py b/lldb/test/expression_command/formatters/formatters.py new file mode 100644 index 00000000000..ce922a8f911 --- /dev/null +++ b/lldb/test/expression_command/formatters/formatters.py @@ -0,0 +1,17 @@ +def foo_SummaryProvider (valobj,dict): + a = valobj.GetChildMemberWithName('a'); + a_ptr = valobj.GetChildMemberWithName('a_ptr'); + bar = valobj.GetChildMemberWithName('b'); + i = bar.GetChildMemberWithName('i'); + i_ptr = bar.GetChildMemberWithName('i_ptr'); + b_ref = bar.GetChildMemberWithName('b_ref'); + b_ref_ptr = b_ref.AddressOf() + b_ref = b_ref_ptr.Dereference() + h = b_ref.GetChildMemberWithName('h'); + k = b_ref.GetChildMemberWithName('k'); + return 'a = ' + str(a.GetValueAsUnsigned(0)) + ', a_ptr = ' + \ + str(a_ptr.GetValueAsUnsigned(0)) + ' -> ' + str(a_ptr.Dereference().GetValueAsUnsigned(0)) + \ + ', i = ' + str(i.GetValueAsUnsigned(0)) + \ + ', i_ptr = ' + str(i_ptr.GetValueAsUnsigned(0)) + ' -> ' + str(i_ptr.Dereference().GetValueAsUnsigned(0)) + \ + ', b_ref = ' + str(b_ref.GetValueAsUnsigned(0)) + \ + ', h = ' + str(h.GetValueAsUnsigned(0)) + ' , k = ' + str(k.GetValueAsUnsigned(0))
\ No newline at end of file diff --git a/lldb/test/expression_command/formatters/main.cpp b/lldb/test/expression_command/formatters/main.cpp new file mode 100644 index 00000000000..4c3b180f370 --- /dev/null +++ b/lldb/test/expression_command/formatters/main.cpp @@ -0,0 +1,48 @@ +#include <iostream> +#include <string> + +struct baz + { + int h; + int k; + baz(int a, int b) : h(a), k(b) {} + }; + +struct bar + { + int i; + int* i_ptr; + baz b; + baz& b_ref; + bar(int x) : i(x),i_ptr(new int(x+1)),b(i+3,i+5),b_ref(b) {} + }; + +struct foo + { + int a; + int* a_ptr; + bar b; + + foo(int x) : a(x), + a_ptr(new int(x+1)), + b(2*x) {} + + }; + +int main(int argc, char** argv) +{ + foo foo1(12); + foo foo2(121); + + foo2.a = 7777; // Stop here + *(foo2.b.i_ptr) = 8888; + foo2.b.b.h = 9999; + + *(foo1.a_ptr) = 9999; + foo1.b.i = 9999; + + int numbers[5] = {1,2,3,4,5}; + + return 0; + +}
\ No newline at end of file diff --git a/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py index 354b1c3e1d2..5eff106a14c 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py @@ -110,10 +110,20 @@ class CppDataFormatterTestCase(TestBase): self.expect("frame variable strarr", substrs = ['arr = "Hello world!']) - + + # check that rdar://problem/10011145 (Standard summary format for char[] doesn't work as the result of "expr".) is solved + self.expect("p strarr", + substrs = ['arr = "Hello world!']) + self.expect("frame variable strptr", substrs = ['ptr = "Hello world!"']) + self.expect("p strptr", + substrs = ['ptr = "Hello world!"']) + + self.expect("p (char*)\"1234567890123456789012345678901234567890123456789012345678901234ABC\"", + substrs = ['(char *) $', ' = ptr = ', ' "1234567890123456789012345678901234567890123456789012345678901234ABC"']) + self.runCmd("type summary add -c Point") self.expect("frame variable iAmSomewhere", diff --git a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py index 67fdb824ab4..e6eed785247 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py @@ -250,6 +250,15 @@ class PythonSynthDataFormatterTestCase(TestBase): '[2] = 123', '[3] = 1234', '}']) + + self.expect("p numbers", + substrs = ['$', '= {', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '}']) + # check access to synthetic children self.runCmd("type summary add --summary-string \"item 0 is ${var[0]}\" std::int_vect int_vect") @@ -278,7 +287,18 @@ class PythonSynthDataFormatterTestCase(TestBase): '[5] = 123456', '[6] = 1234567', '}']) - + + self.expect("p numbers", + substrs = ['$', ' = {', + '[0] = 1', + '[1] = 12', + '[2] = 123', + '[3] = 1234', + '[4] = 12345', + '[5] = 123456', + '[6] = 1234567', + '}']) + # check access-by-index self.expect("frame variable numbers[0]", substrs = ['1']); @@ -320,6 +340,11 @@ class PythonSynthDataFormatterTestCase(TestBase): 'is', 'smart']) + self.expect("p strings", + substrs = ['goofy', + 'is', + 'smart']) + # test summaries based on synthetic children self.runCmd("type summary add std::string_vect string_vect --summary-string \"vector has ${svar%#} items\" -e") self.expect("frame variable strings", @@ -328,6 +353,12 @@ class PythonSynthDataFormatterTestCase(TestBase): 'is', 'smart']) + self.expect("p strings", + substrs = ['vector has 3 items', + 'goofy', + 'is', + 'smart']) + self.runCmd("n"); self.expect("frame variable strings", @@ -360,12 +391,20 @@ class PythonSynthDataFormatterTestCase(TestBase): self.runCmd("type summary add std::int_list std::string_list int_list string_list --summary-string \"list has ${svar%#} items\" -e") self.runCmd("type format add -f hex int") + self.expect("frame variable numbers_list --raw", matching=False, + substrs = ['list has 0 items', + '{}']) + self.expect("frame variable numbers_list", substrs = ['list has 0 items', '{}']) + self.expect("p numbers_list", + substrs = ['list has 0 items', + '{}']) + self.runCmd("n") - + self.expect("frame variable numbers_list", substrs = ['list has 1 items', '[0] = ', @@ -397,7 +436,19 @@ class PythonSynthDataFormatterTestCase(TestBase): '0x0abcdef0', '[5] =', '0x0cab0cab']) - + + self.expect("p numbers_list", + substrs = ['list has 6 items', + '[0] = ', + '0x12345678', + '0x11223344', + '0xbeeffeed', + '0x00abba00', + '[4] =', + '0x0abcdef0', + '[5] =', + '0x0cab0cab']) + # check access-by-index self.expect("frame variable numbers_list[0]", substrs = ['0x12345678']); @@ -414,7 +465,6 @@ class PythonSynthDataFormatterTestCase(TestBase): substrs = ['list has 0 items', '{}']) - self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); self.expect("frame variable numbers_list", @@ -435,16 +485,13 @@ class PythonSynthDataFormatterTestCase(TestBase): self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); self.expect("frame variable text_list", - substrs = ['list has 4 items', - '[0]', 'goofy', - '[1]', 'is', - '[2]', 'smart', - '[3]', '!!!']) - - # let's prettify string display - self.runCmd("type summary add --summary-string \"${var._M_dataplus._M_p}\" std::string std::basic_string<char> \"std::basic_string<char,std::char_traits<char>,std::allocator<char> >\"") + substrs = ['list has 4 items', + '[0]', 'goofy', + '[1]', 'is', + '[2]', 'smart', + '[3]', '!!!']) - self.expect("frame variable text_list", + self.expect("p text_list", substrs = ['list has 4 items', '[0] = \"goofy\"', '[1] = \"is\"', @@ -505,7 +552,7 @@ class PythonSynthDataFormatterTestCase(TestBase): self.runCmd("n");self.runCmd("n"); self.runCmd("n");self.runCmd("n");self.runCmd("n"); - self.expect('frame variable ii', + self.expect("frame variable ii", substrs = ['map has 9 items', '[5] = {', 'first = 5', @@ -514,6 +561,15 @@ class PythonSynthDataFormatterTestCase(TestBase): 'first = 7', 'second = 1']) + self.expect("p ii", + substrs = ['map has 9 items', + '[5] = {', + 'first = 5', + 'second = 0', + '[7] = {', + 'first = 7', + 'second = 1']) + # check access-by-index self.expect("frame variable ii[0]", substrs = ['first = 0', @@ -552,7 +608,7 @@ class PythonSynthDataFormatterTestCase(TestBase): self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); - self.expect('frame variable si', + self.expect("frame variable si", substrs = ['map has 5 items', '[0] = ', 'first = \"zero\"', @@ -569,7 +625,25 @@ class PythonSynthDataFormatterTestCase(TestBase): '[4] = ', 'first = \"four\"', 'second = 4']) - + + self.expect("p si", + substrs = ['map has 5 items', + '[0] = ', + 'first = \"zero\"', + 'second = 0', + '[1] = ', + 'first = \"one\"', + 'second = 1', + '[2] = ', + 'first = \"two\"', + 'second = 2', + '[3] = ', + 'first = \"three\"', + 'second = 3', + '[4] = ', + 'first = \"four\"', + 'second = 4']) + # check access-by-index self.expect("frame variable si[0]", substrs = ['first = ', 'four', @@ -597,7 +671,7 @@ class PythonSynthDataFormatterTestCase(TestBase): self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); - self.expect('frame variable is', + self.expect("frame variable is", substrs = ['map has 4 items', '[0] = ', 'second = \"goofy\"', @@ -612,6 +686,21 @@ class PythonSynthDataFormatterTestCase(TestBase): 'second = \"!!!\"', 'first = 3']) + self.expect("p is", + substrs = ['map has 4 items', + '[0] = ', + 'second = \"goofy\"', + 'first = 0', + '[1] = ', + 'second = \"is\"', + 'first = 1', + '[2] = ', + 'second = \"smart\"', + 'first = 2', + '[3] = ', + 'second = \"!!!\"', + 'first = 3']) + # check access-by-index self.expect("frame variable is[0]", substrs = ['first = ', '0', @@ -639,7 +728,7 @@ class PythonSynthDataFormatterTestCase(TestBase): self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n"); - self.expect('frame variable ss', + self.expect("frame variable ss", substrs = ['map has 4 items', '[0] = ', 'second = \"hello\"', @@ -654,6 +743,21 @@ class PythonSynthDataFormatterTestCase(TestBase): 'second = \"..is always a Mac!\"', 'first = \"a Mac..\"']) + self.expect("p ss", + substrs = ['map has 4 items', + '[0] = ', + 'second = \"hello\"', + 'first = \"ciao\"', + '[1] = ', + 'second = \"house\"', + 'first = \"casa\"', + '[2] = ', + 'second = \"cat\"', + 'first = \"gatto\"', + '[3] = ', + 'second = \"..is always a Mac!\"', + 'first = \"a Mac..\"']) + # check access-by-index self.expect("frame variable ss[3]", substrs = ['gatto', 'cat']); diff --git a/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py b/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py index 096a2f5e5d2..bfce217c56f 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py @@ -79,6 +79,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['arr = \"', 'Nested Hello world!']) + self.expect("p strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs = ['arr = \"', + 'Nested Hello world!']) + # ${var%c} self.runCmd("type summary add --summary-string \"ptr = ${var%c}\" \"char *\"") @@ -90,6 +98,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['ptr = \"', 'Nested Hello world!']) + self.expect("p strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + self.runCmd("type summary add --summary-string \"arr = ${var%c}\" -x \"char \\[[0-9]+\\]\"") self.expect("frame variable strarr", @@ -100,6 +116,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['arr = \"', 'Nested Hello world!']) + self.expect("p strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs = ['arr = \"', + 'Nested Hello world!']) + # ${var%char[]} self.runCmd("type summary add --summary-string \"arr = ${var%char[]}\" -x \"char \\[[0-9]+\\]\"") @@ -111,6 +135,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['arr = ', 'Nested Hello world!']) + self.expect("p strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs = ['arr = ', + 'Nested Hello world!']) + self.runCmd("type summary add --summary-string \"ptr = ${var%char[]}\" \"char *\"") self.expect("frame variable strptr", @@ -121,6 +153,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['ptr = \"', 'Nested Hello world!']) + self.expect("p strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + # ${var%a} self.runCmd("type summary add --summary-string \"arr = ${var%a}\" -x \"char \\[[0-9]+\\]\"") @@ -132,6 +172,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['arr = ', 'Nested Hello world!']) + self.expect("p strarr", + substrs = ['arr = \"', + 'Hello world!']) + + self.expect("p other.strarr", + substrs = ['arr = ', + 'Nested Hello world!']) + self.runCmd("type summary add --summary-string \"ptr = ${var%a}\" \"char *\"") self.expect("frame variable strptr", @@ -142,6 +190,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['ptr = \"', 'Nested Hello world!']) + self.expect("p strptr", + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", + substrs = ['ptr = \"', + 'Nested Hello world!']) + self.runCmd("type summary add --summary-string \"ptr = ${var[]%char[]}\" \"char *\"") # I do not know the size of the data, but you are asking for a full array slice.. @@ -154,6 +210,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['ptr = \"', 'Nested Hello world!']) + self.expect("p strptr", matching=False, + substrs = ['ptr = \"', + 'Hello world!']) + + self.expect("p other.strptr", matching=False, + substrs = ['ptr = \"', + 'Nested Hello world!']) + # You asked an array-style printout... self.runCmd("type summary add --summary-string \"ptr = ${var[0-1]%char[]}\" \"char *\"") @@ -165,6 +229,14 @@ class SmartArrayDataFormatterTestCase(TestBase): substrs = ['ptr = ', '[{N},{e}]']) + self.expect("p strptr", + substrs = ['ptr = ', + '[{H},{e}]']) + + self.expect("p other.strptr", + substrs = ['ptr = ', + '[{N},{e}]']) + # using [] is required here self.runCmd("type summary add --summary-string \"arr = ${var%x}\" \"int [5]\"") diff --git a/lldb/test/functionalities/target_command/TestTargetCommand.py b/lldb/test/functionalities/target_command/TestTargetCommand.py index 600b19eca26..3f0bef3dc35 100644 --- a/lldb/test/functionalities/target_command/TestTargetCommand.py +++ b/lldb/test/functionalities/target_command/TestTargetCommand.py @@ -46,6 +46,15 @@ class targetCommandTestCase(TestBase): self.do_target_variable_command('globals') + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + def test_target_variable_command_with_dsym_no_fail(self): + """Test 'target variable' command before and after starting the inferior.""" + d = {'C_SOURCES': 'globals.c', 'EXE': 'globals'} + self.buildDsym(dictionary=d) + self.addTearDownCleanup(dictionary=d) + + self.do_target_variable_command_no_fail('globals') + def do_target_command(self): """Exercise 'target create', 'target list', 'target select' commands.""" exe_a = os.path.join(os.getcwd(), "a.out") @@ -109,18 +118,78 @@ class targetCommandTestCase(TestBase): substrs = ['my_global_str', '"abc"']) self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['my_static_int', '228']) - + self.expect("target variable my_global_str_ptr", matching=False, + substrs = ['"abc"']) + self.expect("target variable *my_global_str_ptr", matching=True, + substrs = ['"abc"']) + self.expect("target variable *my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['a']) + + self.runCmd("b main") self.runCmd("run") + + self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_global_str', '"abc"']) + self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_static_int', '228']) + self.expect("target variable my_global_str_ptr", matching=False, + substrs = ['"abc"']) + self.expect("target variable *my_global_str_ptr", matching=True, + substrs = ['"abc"']) + self.expect("target variable *my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['a']) + self.expect("target variable my_global_char", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["my_global_char", "'X'"]) + + self.runCmd("c") # rdar://problem/9763907 # 'target variable' command fails if the target program has been run + self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_global_str', '"abc"']) + self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_static_int', '228']) + self.expect("target variable my_global_str_ptr", matching=False, + substrs = ['"abc"']) + self.expect("target variable *my_global_str_ptr", matching=True, + substrs = ['"abc"']) + self.expect("target variable *my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['a']) + self.expect("target variable my_global_char", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["my_global_char", "'X'"]) + + def do_target_variable_command_no_fail(self, exe_name): + """Exercise 'target variable' command before and after starting the inferior.""" + self.runCmd("file " + exe_name, CURRENT_EXECUTABLE_SET) + self.expect("target variable my_global_char", VARIABLES_DISPLAYED_CORRECTLY, substrs = ["my_global_char", "'X'"]) self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['my_global_str', '"abc"']) self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['my_static_int', '228']) - + self.expect("target variable my_global_str_ptr", matching=False, + substrs = ['"abc"']) + self.expect("target variable *my_global_str_ptr", matching=True, + substrs = ['"abc"']) + self.expect("target variable *my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['a']) + + self.runCmd("b main") + self.runCmd("run") + + self.expect("target variable my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_global_str', '"abc"']) + self.expect("target variable my_static_int", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['my_static_int', '228']) + self.expect("target variable my_global_str_ptr", matching=False, + substrs = ['"abc"']) + self.expect("target variable *my_global_str_ptr", matching=True, + substrs = ['"abc"']) + self.expect("target variable *my_global_str", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['a']) + self.expect("target variable my_global_char", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ["my_global_char", "'X'"]) if __name__ == '__main__': import atexit diff --git a/lldb/test/functionalities/target_command/globals.c b/lldb/test/functionalities/target_command/globals.c index 51f08856518..6902bc41568 100644 --- a/lldb/test/functionalities/target_command/globals.c +++ b/lldb/test/functionalities/target_command/globals.c @@ -10,6 +10,7 @@ char my_global_char = 'X'; const char* my_global_str = "abc"; +const char **my_global_str_ptr = &my_global_str; static int my_static_int = 228; int main (int argc, char const *argv[]) diff --git a/lldb/test/lang/c/strings/TestCStrings.py b/lldb/test/lang/c/strings/TestCStrings.py index 84c00a47231..e906ad6ae2c 100644 --- a/lldb/test/lang/c/strings/TestCStrings.py +++ b/lldb/test/lang/c/strings/TestCStrings.py @@ -50,6 +50,15 @@ class CStringsTestCase(TestBase): self.expect("expression -- \"\"[0]", startstr = "(const char) $4 = '\\0'") + self.expect("p \"hello\"", + substrs = ['(const char [6]) $', 'hello', + '(const char) [0] = \'h\'', + '(const char) [5] = \'\\0\'']) + + self.expect("p (char*)\"hello\"", + substrs = ['(char *) $', ' = 0x', + 'hello']) + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() diff --git a/lldb/test/python_api/sbdata/Makefile b/lldb/test/python_api/sbdata/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/test/python_api/sbdata/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/test/python_api/sbdata/TestSBData.py b/lldb/test/python_api/sbdata/TestSBData.py new file mode 100644 index 00000000000..29e201df26d --- /dev/null +++ b/lldb/test/python_api/sbdata/TestSBData.py @@ -0,0 +1,204 @@ +"""Test the SBData APIs.""" + +import os +import unittest2 +import lldb +import pexpect +from lldbtest import * +from math import fabs + +class SBDataAPICase(TestBase): + + mydir = os.path.join("python_api", "sbdata") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test + def test_with_dsym_and_run_command(self): + """Test the SBData APIs.""" + self.buildDsym() + self.data_api() + + @python_api_test + def test_with_dwarf_and_process_launch_api(self): + """Test the SBData APIs.""" + self.buildDwarf() + self.data_api() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break on inside main.cpp. + self.line = line_number('main.cpp', '// set breakpoint here') + + def data_api(self): + """Test the SBData APIs.""" + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET) + + self.expect("breakpoint set -f main.cpp -l %d" % self.line, + BREAKPOINT_CREATED, + startstr = "Breakpoint created: 1: file ='main.cpp', line = %d, locations = 1" % + self.line) + + self.runCmd("run", RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint. + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, + substrs = ['stopped', + 'stop reason = breakpoint']) + + target = self.dbg.GetSelectedTarget() + + process = target.GetProcess() + + thread = process.GetThreadAtIndex(0) + + frame = thread.GetSelectedFrame() + + foobar = frame.FindVariable('foobar') + + print foobar + + data = foobar.GetPointeeData(0, 2) + + print data + + offset = 0 + error = lldb.SBError() + + self.assertTrue(data.GetUnsignedInt32(error, offset) == 1, 'foo[0].a == 1') + offset += 4 + low = data.GetSignedInt16(error, offset) + offset += 2 + high = data.GetSignedInt16(error, offset) + offset += 2 + self.assertTrue ((low == 9 and high == 0) or (low == 0 and high == 9), 'foo[0].b == 9') + self.assertTrue( fabs(data.GetFloat(error, offset) - 3.14) < 1, 'foo[0].c == 3.14') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 8, 'foo[1].a == 8') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 5, 'foo[1].b == 5') + offset += 4 + + self.runCmd("n") + + offset = 16 + + self.assertTrue(data.GetUnsignedInt32(error, offset) == 5, 'saved foo[1].b == 5') + + data = foobar.GetPointeeData(1, 1) + + offset = 0 + + self.assertTrue(data.GetSignedInt32(error, offset) == 8, 'new foo[1].a == 8') + offset += 4 + self.assertTrue(data.GetSignedInt32(error, offset) == 7, 'new foo[1].a == 7') + offset += 8 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 0, 'do not read beyond end') + + star_foobar = foobar.Dereference() + + data = star_foobar.GetData() + + print data + + offset = 0 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 1, 'foo[0].a == 1') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 9, 'foo[0].b == 9') + + foobar_addr = star_foobar.GetLoadAddress() + foobar_addr += 12 + + new_foobar = foobar.CreateValueFromAddress("f00", foobar_addr, star_foobar.GetType()) + + print new_foobar + + data = new_foobar.GetData() + + print data + + offset = 0 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 8, 'then foo[1].a == 8') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 7, 'then foo[1].b == 7') + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 3.14) < 1, 'foo[1].c == 3.14') + + self.runCmd("n") + + offset = 0 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 8, 'then foo[1].a == 8') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 7, 'then foo[1].b == 7') + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 3.14) < 1, 'foo[1].c == 3.14') + + data = new_foobar.GetData() + + print data + + offset = 0 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 8, 'finally foo[1].a == 8') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 7, 'finally foo[1].b == 7') + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 6.28) < 1, 'foo[1].c == 6.28') + + self.runCmd("n") + + barfoo = frame.FindVariable('barfoo') + + data = barfoo.GetData() + + print barfoo + + print data + + offset = 0 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 1, 'barfoo[0].a = 1') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 2, 'barfoo[0].b == 2') + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 3) < 1, 'barfoo[0].c == 3') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 4, 'barfoo[1].a = 4') + offset += 4 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 5, 'barfoo[1].b == 5') + offset += 4 + self.assertTrue(fabs(data.GetFloat(error, offset) - 6) < 1, 'barfoo[1].c == 6') + + new_object = barfoo.CreateValueFromData("new_object",data,barfoo.GetType().GetBasicType(lldb.eBasicTypeInt)) + + print new_object + + self.assertTrue(new_object.GetLoadAddress() == 0xFFFFFFFFFFFFFFFF, 'GetLoadAddress() == invalid') + self.assertTrue(new_object.AddressOf().IsValid() == False, 'AddressOf() == invalid') + self.assertTrue(new_object.GetAddress().IsValid() == False, 'GetAddress() == invalid') + + self.assertTrue(new_object.GetValue() == "1", 'new_object == 1') + + data.SetData(error, 'A\0\0\0', data.GetByteOrder(), data.GetAddressByteSize()) + + data2 = lldb.SBData() + data2.SetData(error, 'BCD', data.GetByteOrder(), data.GetAddressByteSize()) + + data.Append(data2) + + print data + + # this breaks on EBCDIC + offset = 0 + self.assertTrue(data.GetUnsignedInt32(error, offset) == 65, 'made-up data == 65') + offset += 4 + self.assertTrue(data.GetUnsignedInt8(error, offset) == 66, 'made-up data == 66') + offset += 1 + self.assertTrue(data.GetUnsignedInt8(error, offset) == 67, 'made-up data == 67') + offset += 1 + self.assertTrue(data.GetUnsignedInt8(error, offset) == 68, 'made-up data == 68') + offset += 1 + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() diff --git a/lldb/test/python_api/sbdata/main.cpp b/lldb/test/python_api/sbdata/main.cpp new file mode 100644 index 00000000000..6018475d83c --- /dev/null +++ b/lldb/test/python_api/sbdata/main.cpp @@ -0,0 +1,43 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include <stdint.h> + +struct foo +{ + uint32_t a; + uint32_t b; + float c; + foo() : a(0), b(1), c(3.14) {} + foo(uint32_t A, uint32_t B, float C) : + a(A), + b(B), + c(C) + {} +}; + +int main (int argc, char const *argv[]) +{ + foo* foobar = new foo[2]; + + foobar[0].a = 1; + foobar[0].b = 9; + + foobar[1].a = 8; + foobar[1].b = 5; + + foobar[1].b = 7; // set breakpoint here + + foobar[1].c = 6.28; + + foo barfoo[] = {foo(1,2,3), foo(4,5,6)}; + + delete[] foobar; + + return 0; +} |