//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes // C++ Includes #include // Other libraries and framework includes // Project includes #include "GoFormatterFunctions.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/StringPrinter.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; namespace { class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: GoSliceSyntheticFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) { Update(); } ~GoSliceSyntheticFrontEnd() override = default; size_t CalculateNumChildren() override { return m_len; } lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { if (idx < m_len) { ValueObjectSP &cached = m_children[idx]; if (!cached) { StreamString idx_name; idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); lldb::addr_t object_at_idx = m_base_data_address; object_at_idx += idx * m_type.GetByteSize(nullptr); cached = CreateValueObjectFromAddress( idx_name.GetString(), object_at_idx, m_backend.GetExecutionContextRef(), m_type); } return cached; } return ValueObjectSP(); } bool Update() override { size_t old_count = m_len; ConstString array_const_str("array"); ValueObjectSP array_sp = m_backend.GetChildMemberWithName(array_const_str, true); if (!array_sp) { m_children.clear(); return old_count == 0; } m_type = array_sp->GetCompilerType().GetPointeeType(); m_base_data_address = array_sp->GetPointerValue(); ConstString len_const_str("len"); ValueObjectSP len_sp = m_backend.GetChildMemberWithName(len_const_str, true); if (len_sp) { m_len = len_sp->GetValueAsUnsigned(0); m_children.clear(); } return old_count == m_len; } bool MightHaveChildren() override { return true; } size_t GetIndexOfChildWithName(const ConstString &name) override { return ExtractIndexFromString(name.AsCString()); } private: CompilerType m_type; lldb::addr_t m_base_data_address; size_t m_len; std::map m_children; }; } // anonymous namespace bool lldb_private::formatters::GoStringSummaryProvider( ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) { ProcessSP process_sp = valobj.GetProcessSP(); if (!process_sp) return false; if (valobj.IsPointerType()) { Status err; ValueObjectSP deref = valobj.Dereference(err); if (!err.Success()) return false; return GoStringSummaryProvider(*deref, stream, opts); } ConstString str_name("str"); ConstString len_name("len"); ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true); ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true); if (!data_sp || !len_sp) return false; bool success; lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success); if (!success) return false; uint64_t length = len_sp->GetValueAsUnsigned(0); if (length == 0) { stream.Printf("\"\""); return true; } StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); options.SetLocation(valobj_addr); options.SetProcessSP(process_sp); options.SetStream(&stream); options.SetSourceSize(length); options.SetNeedsZeroTermination(false); options.SetLanguage(eLanguageTypeGo); if (!StringPrinter::ReadStringAndDumpToStream< StringPrinter::StringElementType::UTF8>(options)) { stream.Printf("Summary Unavailable"); return true; } return true; } SyntheticChildrenFrontEnd * lldb_private::formatters::GoSliceSyntheticFrontEndCreator( CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) { if (!valobj_sp) return nullptr; lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); if (!process_sp) return nullptr; return new GoSliceSyntheticFrontEnd(*valobj_sp); }