Author: Sylvestre Ledru Date: 2024-12-11T00:00:44+01:00 New Revision: a2fb70523ac310af6d8a4d9663dfe7c9cd370c53
URL: https://github.com/llvm/llvm-project/commit/a2fb70523ac310af6d8a4d9663dfe7c9cd370c53 DIFF: https://github.com/llvm/llvm-project/commit/a2fb70523ac310af6d8a4d9663dfe7c9cd370c53.diff LOG: Revert "[lldb] Add cast to fix compile error on 32-bit platforms" This reverts commit f6012a209dca6b1866d00e6b4f96279469884320. Revert "[lldb] Add cast to fix compile error on 32-but platforms" This reverts commit d300337e93da4ed96b044557e4b0a30001967cf0. Revert "[lldb] Improve log message to include missing strings" This reverts commit 0be33484853557bc0fd9dfb94e0b6c15dda136ce. Revert "[lldb] Add comment" This reverts commit e2bb47443d2e5c022c7851dd6029e3869fc8835c. Revert "[lldb] Implement a formatter bytecode interpreter in C++" This reverts commit 9a9c1d4a6155a96ce9be494cec7e25731d36b33e. Added: Modified: lldb/include/lldb/DataFormatters/FormattersHelpers.h lldb/include/lldb/DataFormatters/TypeSummary.h lldb/include/lldb/lldb-enumerations.h lldb/source/API/SBTypeSummary.cpp lldb/source/Core/Section.cpp lldb/source/DataFormatters/CMakeLists.txt lldb/source/DataFormatters/TypeSummary.cpp lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp lldb/source/Symbol/ObjectFile.cpp lldb/source/Target/Target.cpp lldb/unittests/DataFormatter/CMakeLists.txt Removed: lldb/include/lldb/DataFormatters/FormatterSection.h lldb/source/DataFormatters/FormatterBytecode.cpp lldb/source/DataFormatters/FormatterBytecode.def lldb/source/DataFormatters/FormatterBytecode.h lldb/source/DataFormatters/FormatterSection.cpp lldb/test/API/functionalities/data-formatter/bytecode-summary/Makefile lldb/test/API/functionalities/data-formatter/bytecode-summary/TestBytecodeSummary.py lldb/test/API/functionalities/data-formatter/bytecode-summary/main.cpp lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp ################################################################################ diff --git a/lldb/include/lldb/DataFormatters/FormatterSection.h b/lldb/include/lldb/DataFormatters/FormatterSection.h deleted file mode 100644 index 0613fba6c3a602..00000000000000 --- a/lldb/include/lldb/DataFormatters/FormatterSection.h +++ /dev/null @@ -1,26 +0,0 @@ -//===-- FormattersSection.h -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLDB_DATAFORMATTERS_FORMATTERSECTION_H -#define LLDB_DATAFORMATTERS_FORMATTERSECTION_H - -#include "lldb/lldb-enumerations.h" -#include "lldb/lldb-forward.h" - -namespace lldb_private { -/// Load type summaries embedded in the binary. These are type summaries -/// provided by the authors of the code. -void LoadTypeSummariesForModule(lldb::ModuleSP module_sp); - -/// Load data formatters embedded in the binary. These are formatters provided -/// by the authors of the code using LLDB formatter bytecode. -void LoadFormattersForModule(lldb::ModuleSP module_sp); - -} // namespace lldb_private - -#endif // LLDB_DATAFORMATTERS_FORMATTERSECTION_H diff --git a/lldb/include/lldb/DataFormatters/FormattersHelpers.h b/lldb/include/lldb/DataFormatters/FormattersHelpers.h index a98042fd40f93a..a2e8521d96651b 100644 --- a/lldb/include/lldb/DataFormatters/FormattersHelpers.h +++ b/lldb/include/lldb/DataFormatters/FormattersHelpers.h @@ -1,4 +1,5 @@ -//===-- FormattersHelpers.h -------------------------------------*- C++ -*-===// +//===-- FormattersHelpers.h --------------------------------------*- C++ +//-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/include/lldb/DataFormatters/TypeSummary.h b/lldb/include/lldb/DataFormatters/TypeSummary.h index f4d5563516ecb8..382824aa2813da 100644 --- a/lldb/include/lldb/DataFormatters/TypeSummary.h +++ b/lldb/include/lldb/DataFormatters/TypeSummary.h @@ -22,10 +22,6 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" -namespace llvm { -class MemoryBuffer; -} - namespace lldb_private { class TypeSummaryOptions { public: @@ -48,7 +44,7 @@ class TypeSummaryOptions { class TypeSummaryImpl { public: - enum class Kind { eSummaryString, eScript, eBytecode, eCallback, eInternal }; + enum class Kind { eSummaryString, eScript, eCallback, eInternal }; virtual ~TypeSummaryImpl() = default; @@ -413,23 +409,6 @@ struct ScriptSummaryFormat : public TypeSummaryImpl { ScriptSummaryFormat(const ScriptSummaryFormat &) = delete; const ScriptSummaryFormat &operator=(const ScriptSummaryFormat &) = delete; }; - -/// A summary formatter that is defined in LLDB formmater bytecode. -class BytecodeSummaryFormat : public TypeSummaryImpl { - std::unique_ptr<llvm::MemoryBuffer> m_bytecode; - -public: - BytecodeSummaryFormat(const TypeSummaryImpl::Flags &flags, - std::unique_ptr<llvm::MemoryBuffer> bytecode); - bool FormatObject(ValueObject *valobj, std::string &dest, - const TypeSummaryOptions &options) override; - std::string GetDescription() override; - std::string GetName() override; - static bool classof(const TypeSummaryImpl *S) { - return S->GetKind() == Kind::eBytecode; - } -}; - } // namespace lldb_private #endif // LLDB_DATAFORMATTERS_TYPESUMMARY_H diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 0094fcd596fdf7..e00ec7f17c5cb8 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -764,7 +764,6 @@ enum SectionType { eSectionTypeDWARFDebugTuIndex, eSectionTypeCTF, eSectionTypeLLDBTypeSummaries, - eSectionTypeLLDBFormatters, eSectionTypeSwiftModules, }; diff --git a/lldb/source/API/SBTypeSummary.cpp b/lldb/source/API/SBTypeSummary.cpp index 856ee0ed3175b3..a5e87188c9f630 100644 --- a/lldb/source/API/SBTypeSummary.cpp +++ b/lldb/source/API/SBTypeSummary.cpp @@ -343,7 +343,6 @@ bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) { case TypeSummaryImpl::Kind::eCallback: return llvm::dyn_cast<CXXFunctionSummaryFormat>(m_opaque_sp.get()) == llvm::dyn_cast<CXXFunctionSummaryFormat>(rhs.m_opaque_sp.get()); - case TypeSummaryImpl::Kind::eBytecode: case TypeSummaryImpl::Kind::eScript: if (IsFunctionCode() != rhs.IsFunctionCode()) return false; diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp index 31273ede618f21..ee01b4ce06ca1e 100644 --- a/lldb/source/Core/Section.cpp +++ b/lldb/source/Core/Section.cpp @@ -149,12 +149,10 @@ const char *Section::GetTypeAsCString() const { return "ctf"; case eSectionTypeLLDBTypeSummaries: return "lldb-type-summaries"; - case eSectionTypeLLDBFormatters: - return "lldb-formatters"; - case eSectionTypeSwiftModules: - return "swift-modules"; case eSectionTypeOther: return "regular"; + case eSectionTypeSwiftModules: + return "swift-modules"; } return "unknown"; } @@ -462,7 +460,6 @@ bool Section::ContainsOnlyDebugInfo() const { case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: case eSectionTypeLLDBTypeSummaries: - case eSectionTypeLLDBFormatters: case eSectionTypeSwiftModules: return true; } diff --git a/lldb/source/DataFormatters/CMakeLists.txt b/lldb/source/DataFormatters/CMakeLists.txt index 91b10ba9e0ac8b..13faf65227d2c9 100644 --- a/lldb/source/DataFormatters/CMakeLists.txt +++ b/lldb/source/DataFormatters/CMakeLists.txt @@ -5,9 +5,7 @@ add_lldb_library(lldbDataFormatters NO_PLUGIN_DEPENDENCIES FormatCache.cpp FormatClasses.cpp FormatManager.cpp - FormatterBytecode.cpp FormattersHelpers.cpp - FormatterSection.cpp LanguageCategory.cpp StringPrinter.cpp TypeCategory.cpp diff --git a/lldb/source/DataFormatters/FormatterBytecode.cpp b/lldb/source/DataFormatters/FormatterBytecode.cpp deleted file mode 100644 index 21e90e75202f68..00000000000000 --- a/lldb/source/DataFormatters/FormatterBytecode.cpp +++ /dev/null @@ -1,575 +0,0 @@ -//===-- FormatterBytecode.cpp ---------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "FormatterBytecode.h" -#include "lldb/Utility/LLDBLog.h" -#include "lldb/ValueObject/ValueObject.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/DataExtractor.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/FormatProviders.h" -#include "llvm/Support/FormatVariadicDetails.h" - -using namespace lldb; -namespace lldb_private { - -std::string toString(FormatterBytecode::OpCodes op) { - switch (op) { -#define DEFINE_OPCODE(OP, MNEMONIC, NAME) \ - case OP: { \ - const char *s = MNEMONIC; \ - return s ? s : #NAME; \ - } -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE - } - return llvm::utostr(op); -} - -std::string toString(FormatterBytecode::Selectors sel) { - switch (sel) { -#define DEFINE_SELECTOR(ID, NAME) \ - case ID: \ - return "@" #NAME; -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE - } - return "@" + llvm::utostr(sel); -} - -std::string toString(FormatterBytecode::Signatures sig) { - switch (sig) { -#define DEFINE_SIGNATURE(ID, NAME) \ - case ID: \ - return "@" #NAME; -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE - } - return llvm::utostr(sig); -} - -std::string toString(const FormatterBytecode::DataStack &data) { - std::string s; - llvm::raw_string_ostream os(s); - os << "[ "; - for (auto &d : data) { - if (auto s = std::get_if<std::string>(&d)) - os << '"' << *s << '"'; - else if (auto u = std::get_if<uint64_t>(&d)) - os << *u << 'u'; - else if (auto i = std::get_if<int64_t>(&d)) - os << *i; - else if (auto valobj = std::get_if<ValueObjectSP>(&d)) { - if (!valobj->get()) - os << "null"; - else - os << "object(" << valobj->get()->GetValueAsCString() << ')'; - } else if (auto type = std::get_if<CompilerType>(&d)) { - os << '(' << type->GetTypeName(true) << ')'; - } else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&d)) { - os << toString(*sel); - } - os << ' '; - } - os << ']'; - return s; -} - -namespace FormatterBytecode { - -/// Implement the @format function. -static llvm::Error FormatImpl(DataStack &data) { - auto fmt = data.Pop<std::string>(); - auto replacements = - llvm::formatv_object_base::parseFormatString(fmt, 0, false); - std::string s; - llvm::raw_string_ostream os(s); - unsigned num_args = 0; - for (const auto &r : replacements) - if (r.Type == llvm::ReplacementType::Format) - num_args = std::max(num_args, r.Index + 1); - - if (data.size() < num_args) - return llvm::createStringError("not enough arguments"); - - for (const auto &r : replacements) { - if (r.Type == llvm::ReplacementType::Literal) { - os << r.Spec; - continue; - } - using namespace llvm::support::detail; - auto arg = data[data.size() - num_args + r.Index]; - auto format = [&](format_adapter &&adapter) { - llvm::FmtAlign Align(adapter, r.Where, r.Width, r.Pad); - Align.format(os, r.Options); - }; - - if (auto s = std::get_if<std::string>(&arg)) - format(build_format_adapter(s->c_str())); - else if (auto u = std::get_if<uint64_t>(&arg)) - format(build_format_adapter(u)); - else if (auto i = std::get_if<int64_t>(&arg)) - format(build_format_adapter(i)); - else if (auto valobj = std::get_if<ValueObjectSP>(&arg)) { - if (!valobj->get()) - format(build_format_adapter("null object")); - else - format(build_format_adapter(valobj->get()->GetValueAsCString())); - } else if (auto type = std::get_if<CompilerType>(&arg)) - format(build_format_adapter(type->GetDisplayTypeName())); - else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&arg)) - format(build_format_adapter(toString(*sel))); - } - data.Push(s); - return llvm::Error::success(); -} - -static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data, - DataType type) { - if (data.size() < 1) - return llvm::createStringError("not enough elements on data stack"); - - auto &elem = data.back(); - switch (type) { - case Any: - break; - case String: - if (!std::holds_alternative<std::string>(elem)) - return llvm::createStringError("expected String"); - break; - case UInt: - if (!std::holds_alternative<uint64_t>(elem)) - return llvm::createStringError("expected UInt"); - break; - case Int: - if (!std::holds_alternative<int64_t>(elem)) - return llvm::createStringError("expected Int"); - break; - case Object: - if (!std::holds_alternative<ValueObjectSP>(elem)) - return llvm::createStringError("expected Object"); - break; - case Type: - if (!std::holds_alternative<CompilerType>(elem)) - return llvm::createStringError("expected Type"); - break; - case Selector: - if (!std::holds_alternative<Selectors>(elem)) - return llvm::createStringError("expected Selector"); - break; - } - return llvm::Error::success(); -} - -static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data, - DataType type1, DataType type2) { - if (auto error = TypeCheck(data, type2)) - return error; - return TypeCheck(data.drop_back(), type1); -} - -static llvm::Error TypeCheck(llvm::ArrayRef<DataStackElement> data, - DataType type1, DataType type2, DataType type3) { - if (auto error = TypeCheck(data, type3)) - return error; - return TypeCheck(data.drop_back(1), type2, type1); -} - -llvm::Error Interpret(std::vector<ControlStackElement> &control, - DataStack &data, Selectors sel) { - if (control.empty()) - return llvm::Error::success(); - // Since the only data types are single endian and ULEBs, the - // endianness should not matter. - llvm::DataExtractor cur_block(control.back(), true, 64); - llvm::DataExtractor::Cursor pc(0); - - while (!control.empty()) { - /// Activate the top most block from the control stack. - auto activate_block = [&]() { - // Save the return address. - if (control.size() > 1) - control[control.size() - 2] = cur_block.getData().drop_front(pc.tell()); - cur_block = llvm::DataExtractor(control.back(), true, 64); - if (pc) - pc = llvm::DataExtractor::Cursor(0); - }; - - /// Fetch the next byte in the instruction stream. - auto next_byte = [&]() -> uint8_t { - // At the end of the current block? - while (pc.tell() >= cur_block.size() && !control.empty()) { - if (control.size() == 1) { - control.pop_back(); - return 0; - } - control.pop_back(); - activate_block(); - } - - // Fetch the next instruction. - return cur_block.getU8(pc); - }; - - // Fetch the next opcode. - OpCodes opcode = (OpCodes)next_byte(); - if (control.empty() || !pc) - return pc.takeError(); - - LLDB_LOGV(GetLog(LLDBLog::DataFormatters), - "[eval {0}] opcode={1}, control={2}, data={3}", toString(sel), - toString(opcode), control.size(), toString(data)); - - // Various shorthands to improve the readability of error handling. -#define TYPE_CHECK(...) \ - if (auto error = TypeCheck(data, __VA_ARGS__)) \ - return error; - - auto error = [&](llvm::Twine msg) { - return llvm::createStringError(msg + "(opcode=" + toString(opcode) + ")"); - }; - - switch (opcode) { - // Data stack manipulation. - case op_dup: - TYPE_CHECK(Any); - data.Push(data.back()); - continue; - case op_drop: - TYPE_CHECK(Any); - data.pop_back(); - continue; - case op_pick: { - TYPE_CHECK(UInt); - uint64_t idx = data.Pop<uint64_t>(); - if (idx >= data.size()) - return error("index out of bounds"); - data.Push(data[idx]); - continue; - } - case op_over: - TYPE_CHECK(Any, Any); - data.Push(data[data.size() - 2]); - continue; - case op_swap: { - TYPE_CHECK(Any, Any); - auto x = data.PopAny(); - auto y = data.PopAny(); - data.Push(x); - data.Push(y); - continue; - } - case op_rot: { - TYPE_CHECK(Any, Any, Any); - auto z = data.PopAny(); - auto y = data.PopAny(); - auto x = data.PopAny(); - data.Push(z); - data.Push(x); - data.Push(y); - continue; - } - - // Control stack manipulation. - case op_begin: { - uint64_t length = cur_block.getULEB128(pc); - if (!pc) - return pc.takeError(); - llvm::StringRef block = cur_block.getBytes(pc, length); - if (!pc) - return pc.takeError(); - control.push_back(block); - continue; - } - case op_if: - TYPE_CHECK(UInt); - if (data.Pop<uint64_t>() != 0) { - if (!cur_block.size()) - return error("empty control stack"); - activate_block(); - } else - control.pop_back(); - continue; - case op_ifelse: - TYPE_CHECK(UInt); - if (cur_block.size() < 2) - return error("empty control stack"); - if (data.Pop<uint64_t>() == 0) - control[control.size() - 2] = control.back(); - control.pop_back(); - activate_block(); - continue; - - // Literals. - case op_lit_uint: - data.Push(cur_block.getULEB128(pc)); - continue; - case op_lit_int: - data.Push(cur_block.getSLEB128(pc)); - continue; - case op_lit_selector: - data.Push(Selectors(cur_block.getU8(pc))); - continue; - case op_lit_string: { - uint64_t length = cur_block.getULEB128(pc); - llvm::StringRef bytes = cur_block.getBytes(pc, length); - data.Push(bytes.str()); - continue; - } - case op_as_uint: { - TYPE_CHECK(Int); - uint64_t casted; - int64_t val = data.Pop<int64_t>(); - memcpy(&casted, &val, sizeof(val)); - data.Push(casted); - continue; - } - case op_as_int: { - TYPE_CHECK(UInt); - int64_t casted; - uint64_t val = data.Pop<uint64_t>(); - memcpy(&casted, &val, sizeof(val)); - data.Push(casted); - continue; - } - case op_is_null: { - TYPE_CHECK(Object); - data.Push(data.Pop<ValueObjectSP>() ? 0ULL : 1ULL); - continue; - } - - // Arithmetic, logic, etc. -#define BINOP_IMPL(OP, CHECK_ZERO) \ - { \ - TYPE_CHECK(Any, Any); \ - auto y = data.PopAny(); \ - if (std::holds_alternative<uint64_t>(y)) { \ - if (CHECK_ZERO && !std::get<uint64_t>(y)) \ - return error(#OP " by zero"); \ - TYPE_CHECK(UInt); \ - data.Push((uint64_t)(data.Pop<uint64_t>() OP std::get<uint64_t>(y))); \ - } else if (std::holds_alternative<int64_t>(y)) { \ - if (CHECK_ZERO && !std::get<int64_t>(y)) \ - return error(#OP " by zero"); \ - TYPE_CHECK(Int); \ - data.Push((int64_t)(data.Pop<int64_t>() OP std::get<int64_t>(y))); \ - } else \ - return error("unsupported data types"); \ - } -#define BINOP(OP) BINOP_IMPL(OP, false) -#define BINOP_CHECKZERO(OP) BINOP_IMPL(OP, true) - case op_plus: - BINOP(+); - continue; - case op_minus: - BINOP(-); - continue; - case op_mul: - BINOP(*); - continue; - case op_div: - BINOP_CHECKZERO(/); - continue; - case op_mod: - BINOP_CHECKZERO(%); - continue; - case op_shl: -#define SHIFTOP(OP) \ - { \ - TYPE_CHECK(Any, UInt); \ - uint64_t y = data.Pop<uint64_t>(); \ - if (y > 64) \ - return error("shift out of bounds"); \ - if (std::holds_alternative<uint64_t>(data.back())) { \ - uint64_t x = data.Pop<uint64_t>(); \ - data.Push(x OP y); \ - } else if (std::holds_alternative<int64_t>(data.back())) { \ - int64_t x = data.Pop<int64_t>(); \ - if (y > 64) \ - return error("shift out of bounds"); \ - if (y < 0) \ - return error("shift out of bounds"); \ - data.Push(x OP y); \ - } else \ - return error("unsupported data types"); \ - } - SHIFTOP(<<); - continue; - case op_shr: - SHIFTOP(<<); - continue; - case op_and: - BINOP(&); - continue; - case op_or: - BINOP(|); - continue; - case op_xor: - BINOP(^); - continue; - case op_not: - TYPE_CHECK(UInt); - data.Push(~data.Pop<uint64_t>()); - continue; - case op_eq: - BINOP(==); - continue; - case op_neq: - BINOP(!=); - continue; - case op_lt: - BINOP(<); - continue; - case op_gt: - BINOP(>); - continue; - case op_le: - BINOP(<=); - continue; - case op_ge: - BINOP(>=); - continue; - case op_call: { - TYPE_CHECK(Selector); - Selectors sel = data.Pop<Selectors>(); - - // Shorthand to improve readability. -#define POP_VALOBJ(VALOBJ) \ - auto VALOBJ = data.Pop<ValueObjectSP>(); \ - if (!VALOBJ) \ - return error("null object"); - - auto sel_error = [&](const char *msg) { - return llvm::createStringError("{0} (opcode={1}, selector={2})", msg, - toString(opcode).c_str(), - toString(sel).c_str()); - }; - - switch (sel) { - case sel_summary: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - const char *summary = valobj->GetSummaryAsCString(); - data.Push(summary ? std::string(valobj->GetSummaryAsCString()) - : std::string()); - break; - } - case sel_get_num_children: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - auto result = valobj->GetNumChildren(); - if (!result) - return result.takeError(); - data.Push((uint64_t)*result); - break; - } - case sel_get_child_at_index: { - TYPE_CHECK(Object, UInt); - auto index = data.Pop<uint64_t>(); - POP_VALOBJ(valobj); - data.Push(valobj->GetChildAtIndex(index)); - break; - } - case sel_get_child_with_name: { - TYPE_CHECK(Object, String); - auto name = data.Pop<std::string>(); - POP_VALOBJ(valobj); - data.Push(valobj->GetChildMemberWithName(name)); - break; - } - case sel_get_child_index: { - TYPE_CHECK(Object, String); - auto name = data.Pop<std::string>(); - POP_VALOBJ(valobj); - data.Push((uint64_t)valobj->GetIndexOfChildWithName(name)); - break; - } - case sel_get_type: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - // FIXME: do we need to control dynamic type resolution? - data.Push(valobj->GetTypeImpl().GetCompilerType(false)); - break; - } - case sel_get_template_argument_type: { - TYPE_CHECK(Type, UInt); - auto index = data.Pop<uint64_t>(); - auto type = data.Pop<CompilerType>(); - // FIXME: There is more code in SBType::GetTemplateArgumentType(). - data.Push(type.GetTypeTemplateArgument(index, true)); - break; - } - case sel_get_value: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - data.Push(std::string(valobj->GetValueAsCString())); - break; - } - case sel_get_value_as_unsigned: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - bool success; - uint64_t val = valobj->GetValueAsUnsigned(0, &success); - data.Push(val); - if (!success) - return sel_error("failed to get value"); - break; - } - case sel_get_value_as_signed: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - bool success; - int64_t val = valobj->GetValueAsSigned(0, &success); - data.Push(val); - if (!success) - return sel_error("failed to get value"); - break; - } - case sel_get_value_as_address: { - TYPE_CHECK(Object); - POP_VALOBJ(valobj); - bool success; - uint64_t addr = valobj->GetValueAsUnsigned(0, &success); - if (!success) - return sel_error("failed to get value"); - if (auto process_sp = valobj->GetProcessSP()) - addr = process_sp->FixDataAddress(addr); - data.Push(addr); - break; - } - case sel_cast: { - TYPE_CHECK(Object, Type); - auto type = data.Pop<CompilerType>(); - POP_VALOBJ(valobj); - data.Push(valobj->Cast(type)); - break; - } - case sel_strlen: { - TYPE_CHECK(String); - data.Push((uint64_t)data.Pop<std::string>().size()); - break; - } - case sel_fmt: { - TYPE_CHECK(String); - if (auto error = FormatImpl(data)) - return error; - break; - } - default: - return sel_error("selector not implemented"); - } - continue; - } - } - return error("opcode not implemented"); - } - return pc.takeError(); -} -} // namespace FormatterBytecode - -} // namespace lldb_private diff --git a/lldb/source/DataFormatters/FormatterBytecode.def b/lldb/source/DataFormatters/FormatterBytecode.def deleted file mode 100644 index c6645631fa0065..00000000000000 --- a/lldb/source/DataFormatters/FormatterBytecode.def +++ /dev/null @@ -1,101 +0,0 @@ -//===-- FormatterBytecode.def -----------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef DEFINE_OPCODE -#define DEFINE_OPCODE(OP, MNEMONIC, NAME) -#endif -#ifndef DEFINE_SELECTOR -#define DEFINE_SELECTOR(ID, NAME) -#endif -#ifndef DEFINE_SIGNATURE -#define DEFINE_SIGNATURE(ID, NAME) -#endif - -// Opcodes. -DEFINE_OPCODE(0x01, "dup", dup) -DEFINE_OPCODE(0x02, "drop", drop) -DEFINE_OPCODE(0x03, "pick", pick) -DEFINE_OPCODE(0x04, "over", over) -DEFINE_OPCODE(0x05, "swap", swap) -DEFINE_OPCODE(0x06, "rot", rot) - -DEFINE_OPCODE(0x10, "{", begin) -DEFINE_OPCODE(0x11, "if", if) -DEFINE_OPCODE(0x12, "ifelse", ifelse) - -DEFINE_OPCODE(0x20, nullptr, lit_uint) -DEFINE_OPCODE(0x21, nullptr, lit_int) -DEFINE_OPCODE(0x22, nullptr, lit_string) -DEFINE_OPCODE(0x23, nullptr, lit_selector) - -DEFINE_OPCODE(0x2a, "as_int", as_int) -DEFINE_OPCODE(0x2b, "as_uint", as_uint) -DEFINE_OPCODE(0x2c, "is_null", is_null) - -DEFINE_OPCODE(0x30, "+", plus) -DEFINE_OPCODE(0x31, "-", minus) -DEFINE_OPCODE(0x32, "*", mul) -DEFINE_OPCODE(0x33, "/", div) -DEFINE_OPCODE(0x34, "%", mod) -DEFINE_OPCODE(0x35, "<<", shl) -DEFINE_OPCODE(0x36, ">>", shr) - -DEFINE_OPCODE(0x40, "&", and) -DEFINE_OPCODE(0x41, "|", or) -DEFINE_OPCODE(0x42, "^", xor) -DEFINE_OPCODE(0x43, "~", not) - -DEFINE_OPCODE(0x50, "=", eq) -DEFINE_OPCODE(0x51, "!=", neq) -DEFINE_OPCODE(0x52, "<", lt) -DEFINE_OPCODE(0x53, ">", gt) -DEFINE_OPCODE(0x54, "=<", le) -DEFINE_OPCODE(0x55, ">=", ge) - -DEFINE_OPCODE(0x60, "call", call) - -// Selectors. -DEFINE_SELECTOR(0x00, summary) -DEFINE_SELECTOR(0x01, type_summary) - -DEFINE_SELECTOR(0x10, get_num_children) -DEFINE_SELECTOR(0x11, get_child_at_index) -DEFINE_SELECTOR(0x12, get_child_with_name) -DEFINE_SELECTOR(0x13, get_child_index) -DEFINE_SELECTOR(0x15, get_type) -DEFINE_SELECTOR(0x16, get_template_argument_type) -DEFINE_SELECTOR(0x17, cast) - -DEFINE_SELECTOR(0x20, get_value) -DEFINE_SELECTOR(0x21, get_value_as_unsigned) -DEFINE_SELECTOR(0x22, get_value_as_signed) -DEFINE_SELECTOR(0x23, get_value_as_address) - -DEFINE_SELECTOR(0x40, read_memory_byte) -DEFINE_SELECTOR(0x41, read_memory_uint32) -DEFINE_SELECTOR(0x42, read_memory_int32) -DEFINE_SELECTOR(0x43, read_memory_unsigned) -DEFINE_SELECTOR(0x44, read_memory_signed) -DEFINE_SELECTOR(0x45, read_memory_address) -DEFINE_SELECTOR(0x46, read_memory) - -DEFINE_SELECTOR(0x50, fmt) -DEFINE_SELECTOR(0x51, sprintf) -DEFINE_SELECTOR(0x52, strlen) - -// Formatter signatures. -DEFINE_SIGNATURE(0, summary) -DEFINE_SIGNATURE(1, init) -DEFINE_SIGNATURE(2, get_num_children) -DEFINE_SIGNATURE(3, get_child_index) -DEFINE_SIGNATURE(4, get_child_at_index) -DEFINE_SIGNATURE(5, get_value) - -#undef DEFINE_OPCODE -#undef DEFINE_SELECTOR -#undef DEFINE_SIGNATURE diff --git a/lldb/source/DataFormatters/FormatterBytecode.h b/lldb/source/DataFormatters/FormatterBytecode.h deleted file mode 100644 index 21454d9c7e231f..00000000000000 --- a/lldb/source/DataFormatters/FormatterBytecode.h +++ /dev/null @@ -1,64 +0,0 @@ -//===-- FormatterBytecode.h -------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/DataFormatters/TypeSummary.h" -#include "lldb/Symbol/CompilerType.h" - -namespace lldb_private { - -namespace FormatterBytecode { - -enum DataType : uint8_t { Any, String, Int, UInt, Object, Type, Selector }; - -enum OpCodes : uint8_t { -#define DEFINE_OPCODE(OP, MNEMONIC, NAME) op_##NAME = OP, -#include "FormatterBytecode.def" -#undef DEFINE_OPCODE -}; - -enum Selectors : uint8_t { -#define DEFINE_SELECTOR(ID, NAME) sel_##NAME = ID, -#include "FormatterBytecode.def" -#undef DEFINE_SELECTOR -}; - -enum Signatures : uint8_t { -#define DEFINE_SIGNATURE(ID, NAME) sig_##NAME = ID, -#include "FormatterBytecode.def" -#undef DEFINE_SIGNATURE -}; - -using ControlStackElement = llvm::StringRef; -using DataStackElement = - std::variant<std::string, uint64_t, int64_t, lldb::ValueObjectSP, - CompilerType, Selectors>; -struct DataStack : public std::vector<DataStackElement> { - DataStack() = default; - DataStack(lldb::ValueObjectSP initial_value) - : std::vector<DataStackElement>({initial_value}) {} - void Push(DataStackElement el) { push_back(el); } - template <typename T> T Pop() { - T el = std::get<T>(back()); - pop_back(); - return el; - } - DataStackElement PopAny() { - DataStackElement el = back(); - pop_back(); - return el; - } -}; -llvm::Error Interpret(std::vector<ControlStackElement> &control, - DataStack &data, Selectors sel); -} // namespace FormatterBytecode - -std::string toString(FormatterBytecode::OpCodes op); -std::string toString(FormatterBytecode::Selectors sel); -std::string toString(FormatterBytecode::Signatures sig); - -} // namespace lldb_private diff --git a/lldb/source/DataFormatters/FormatterSection.cpp b/lldb/source/DataFormatters/FormatterSection.cpp deleted file mode 100644 index f70f41fdeb736f..00000000000000 --- a/lldb/source/DataFormatters/FormatterSection.cpp +++ /dev/null @@ -1,163 +0,0 @@ -//===-- FormatterBytecode.cpp ---------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "FormatterBytecode.h" -#include "lldb/Core/Module.h" -#include "lldb/DataFormatters/DataVisualization.h" -#include "lldb/Utility/LLDBLog.h" - -using namespace lldb; - -namespace lldb_private { -static void ForEachFormatterInModule( - Module &module, SectionType section_type, - std::function<void(llvm::DataExtractor, llvm::StringRef)> fn) { - auto *sections = module.GetSectionList(); - if (!sections) - return; - - auto section_sp = sections->FindSectionByType(section_type, true); - if (!section_sp) - return; - - TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString("default"), category); - - // The type summary record is serialized as follows. - // - // Each record contains, in order: - // * Version number of the record format - // * The remaining size of the record - // * The size of the type identifier - // * The type identifier, either a type name, or a regex - // * The size of the entry - // * The entry - // - // Integers are encoded using ULEB. - // - // Strings are encoded with first a length (ULEB), then the string contents, - // and lastly a null terminator. The length includes the null. - - DataExtractor lldb_extractor; - auto section_size = section_sp->GetSectionData(lldb_extractor); - llvm::DataExtractor section = lldb_extractor.GetAsLLVM(); - bool le = section.isLittleEndian(); - uint8_t addr_size = section.getAddressSize(); - llvm::DataExtractor::Cursor cursor(0); - while (cursor && cursor.tell() < section_size) { - uint64_t version = section.getULEB128(cursor); - uint64_t record_size = section.getULEB128(cursor); - if (version == 1) { - llvm::DataExtractor record(section.getData().drop_front(cursor.tell()), - le, addr_size); - llvm::DataExtractor::Cursor cursor(0); - uint64_t type_size = record.getULEB128(cursor); - llvm::StringRef type_name = record.getBytes(cursor, type_size); - llvm::Error error = cursor.takeError(); - if (!error) - fn(llvm::DataExtractor(record.getData().drop_front(cursor.tell()), le, - addr_size), - type_name); - else - LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(error), - "{0}"); - } else { - // Skip unsupported record. - LLDB_LOG( - GetLog(LLDBLog::DataFormatters), - "Skipping unsupported embedded type summary of version {0} in {1}.", - version, module.GetFileSpec()); - } - section.skip(cursor, record_size); - } - if (!cursor) - LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(), "{0}"); -} - -void LoadTypeSummariesForModule(ModuleSP module_sp) { - ForEachFormatterInModule( - *module_sp, eSectionTypeLLDBTypeSummaries, - [&](llvm::DataExtractor extractor, llvm::StringRef type_name) { - TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString("default"), - category); - // The type summary record is serialized as follows. - // - // * The size of the summary string - // * The summary string - // - // Integers are encoded using ULEB. - llvm::DataExtractor::Cursor cursor(0); - uint64_t summary_size = extractor.getULEB128(cursor); - llvm::StringRef summary_string = - extractor.getBytes(cursor, summary_size); - if (!cursor) { - LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(), - "{0}"); - return; - } - if (type_name.empty() || summary_string.empty()) { - LLDB_LOG(GetLog(LLDBLog::DataFormatters), - "Missing string(s) in embedded type summary in {0}, " - "type_name={1}, summary={2}", - module_sp->GetFileSpec(), type_name, summary_string); - return; - } - TypeSummaryImpl::Flags flags; - auto summary_sp = std::make_shared<StringSummaryFormat>( - flags, summary_string.str().c_str()); - FormatterMatchType match_type = eFormatterMatchExact; - if (type_name.front() == '^') - match_type = eFormatterMatchRegex; - category->AddTypeSummary(type_name, match_type, summary_sp); - LLDB_LOG(GetLog(LLDBLog::DataFormatters), - "Loaded embedded type summary for '{0}' from {1}.", type_name, - module_sp->GetFileSpec()); - }); -} - -void LoadFormattersForModule(ModuleSP module_sp) { - ForEachFormatterInModule( - *module_sp, eSectionTypeLLDBFormatters, - [&](llvm::DataExtractor extractor, llvm::StringRef type_name) { - // * Function signature (1 byte) - // * Length of the program (ULEB128) - // * The program bytecode - TypeCategoryImplSP category; - DataVisualization::Categories::GetCategory(ConstString("default"), - category); - llvm::DataExtractor::Cursor cursor(0); - uint64_t flags = extractor.getULEB128(cursor); - while (cursor && cursor.tell() < extractor.size()) { - uint8_t signature = extractor.getU8(cursor); - uint64_t size = extractor.getULEB128(cursor); - llvm::StringRef bytecode = extractor.getBytes(cursor, size); - if (!cursor) { - LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(), - "{0}"); - return; - } - if (signature == 0) { - auto summary_sp = std::make_shared<BytecodeSummaryFormat>( - TypeSummaryImpl::Flags(flags), - llvm::MemoryBuffer::getMemBufferCopy(bytecode)); - FormatterMatchType match_type = eFormatterMatchExact; - if (type_name.front() == '^') - match_type = eFormatterMatchRegex; - category->AddTypeSummary(type_name, match_type, summary_sp); - LLDB_LOG(GetLog(LLDBLog::DataFormatters), - "Loaded embedded type summary for '{0}' from {1}.", - type_name, module_sp->GetFileSpec()); - } else - LLDB_LOG(GetLog(LLDBLog::DataFormatters), - "Unsupported formatter signature {0} for '{1}' in {2}", - signature, type_name, module_sp->GetFileSpec()); - } - }); -} -} // namespace lldb_private diff --git a/lldb/source/DataFormatters/TypeSummary.cpp b/lldb/source/DataFormatters/TypeSummary.cpp index 2c863b364538f3..3538c1b60c8e9e 100644 --- a/lldb/source/DataFormatters/TypeSummary.cpp +++ b/lldb/source/DataFormatters/TypeSummary.cpp @@ -8,7 +8,9 @@ #include "lldb/DataFormatters/TypeSummary.h" -#include "FormatterBytecode.h" + + + #include "lldb/lldb-enumerations.h" #include "lldb/lldb-public.h" @@ -56,8 +58,6 @@ std::string TypeSummaryImpl::GetSummaryKindName() { return "python"; case Kind::eInternal: return "c++"; - case Kind::eBytecode: - return "bytecode"; } } @@ -230,74 +230,3 @@ std::string ScriptSummaryFormat::GetDescription() { } std::string ScriptSummaryFormat::GetName() { return m_script_formatter_name; } - -BytecodeSummaryFormat::BytecodeSummaryFormat( - const TypeSummaryImpl::Flags &flags, - std::unique_ptr<llvm::MemoryBuffer> bytecode) - : TypeSummaryImpl(Kind::eBytecode, flags), m_bytecode(std::move(bytecode)) { -} - -bool BytecodeSummaryFormat::FormatObject(ValueObject *valobj, - std::string &retval, - const TypeSummaryOptions &options) { - if (!valobj) - return false; - - TargetSP target_sp(valobj->GetTargetSP()); - - if (!target_sp) { - retval.assign("error: no target"); - return false; - } - - std::vector<FormatterBytecode::ControlStackElement> control( - {m_bytecode->getBuffer()}); - FormatterBytecode::DataStack data({valobj->GetSP()}); - llvm::Error error = FormatterBytecode::Interpret( - control, data, FormatterBytecode::sel_summary); - if (error) { - retval = llvm::toString(std::move(error)); - return false; - } - if (!data.size()) { - retval = "empty stack"; - return false; - } - auto &top = data.back(); - retval = ""; - llvm::raw_string_ostream os(retval); - if (auto s = std::get_if<std::string>(&top)) - os << *s; - else if (auto u = std::get_if<uint64_t>(&top)) - os << *u; - else if (auto i = std::get_if<int64_t>(&top)) - os << *i; - else if (auto valobj = std::get_if<ValueObjectSP>(&top)) { - if (!valobj->get()) - os << "empty object"; - else - os << valobj->get()->GetValueAsCString(); - } else if (auto type = std::get_if<CompilerType>(&top)) { - os << type->TypeDescription(); - } else if (auto sel = std::get_if<FormatterBytecode::Selectors>(&top)) { - os << toString(*sel); - } - return true; -} - -std::string BytecodeSummaryFormat::GetDescription() { - StreamString sstr; - sstr.Printf("%s%s%s%s%s%s%s\n ", Cascades() ? "" : " (not cascading)", - !DoesPrintChildren(nullptr) ? "" : " (show children)", - !DoesPrintValue(nullptr) ? " (hide value)" : "", - IsOneLiner() ? " (one-line printout)" : "", - SkipsPointers() ? " (skip pointers)" : "", - SkipsReferences() ? " (skip references)" : "", - HideNames(nullptr) ? " (hide member names)" : ""); - // FIXME: sstr.PutCString(disassembly); - return std::string(sstr.GetString()); -} - -std::string BytecodeSummaryFormat::GetName() { - return "LLDB bytecode formatter"; -} diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index b16cb114bec88e..a8249cf103833e 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1697,7 +1697,6 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) { .Case(".gosymtab", eSectionTypeGoSymtab) .Case(".text", eSectionTypeCode) .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries) - .Case(".lldbformatters", lldb::eSectionTypeLLDBFormatters) .Case(".swift_ast", eSectionTypeSwiftModules) .Default(eSectionTypeOther); } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 488c9bd1e54af1..7e17fd8c53cd01 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -1210,7 +1210,6 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) { case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: case eSectionTypeLLDBTypeSummaries: - case eSectionTypeLLDBFormatters: case eSectionTypeSwiftModules: return AddressClass::eDebug; @@ -1487,7 +1486,6 @@ static lldb::SectionType GetSectionType(uint32_t flags, static ConstString g_sect_name_go_symtab("__gosymtab"); static ConstString g_sect_name_ctf("__ctf"); static ConstString g_sect_name_lldb_summaries("__lldbsummaries"); - static ConstString g_sect_name_lldb_formatters("__lldbformatters"); static ConstString g_sect_name_swift_ast("__swift_ast"); if (section_name == g_sect_name_dwarf_debug_abbrev) @@ -1570,8 +1568,6 @@ static lldb::SectionType GetSectionType(uint32_t flags, return eSectionTypeCTF; if (section_name == g_sect_name_lldb_summaries) return lldb::eSectionTypeLLDBTypeSummaries; - if (section_name == g_sect_name_lldb_formatters) - return lldb::eSectionTypeLLDBFormatters; if (section_name == g_sect_name_swift_ast) return eSectionTypeSwiftModules; if (section_name == g_sect_name_objc_data || diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index bfdb8140e40aff..bb712da7f6d67d 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -1011,7 +1011,6 @@ SectionType ObjectFilePECOFF::GetSectionType(llvm::StringRef sect_name, .Cases(".eh_frame", ".eh_fram", eSectionTypeEHFrame) .Case(".gosymtab", eSectionTypeGoSymtab) .Case(".lldbsummaries", lldb::eSectionTypeLLDBTypeSummaries) - .Case(".lldbformatters", lldb::eSectionTypeLLDBFormatters) .Case("swiftast", eSectionTypeSwiftModules) .Default(eSectionTypeInvalid); if (section_type != eSectionTypeInvalid) diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index d3881f8ccf7fe8..3100e6b813b631 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -366,7 +366,6 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) { case eSectionTypeDWARFAppleObjC: case eSectionTypeDWARFGNUDebugAltLink: case eSectionTypeCTF: - case eSectionTypeLLDBFormatters: case eSectionTypeLLDBTypeSummaries: case eSectionTypeSwiftModules: return AddressClass::eDebug; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 46216ba2d566d7..9ac85ad3ed5ee6 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -24,7 +24,9 @@ #include "lldb/Core/Section.h" #include "lldb/Core/SourceManager.h" #include "lldb/Core/StructuredDataImpl.h" -#include "lldb/DataFormatters/FormatterSection.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/DataFormatters/DataVisualization.h" #include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/REPL.h" @@ -64,6 +66,8 @@ #include "lldb/Utility/State.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" +#include "lldb/ValueObject/ValueObject.h" +#include "lldb/ValueObject/ValueObjectConstResult.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SetVector.h" @@ -1537,6 +1541,76 @@ static void LoadScriptingResourceForModule(const ModuleSP &module_sp, feedback_stream.GetData()); } +// Load type summaries embedded in the binary. These are type summaries provided +// by the authors of the code. +static void LoadTypeSummariesForModule(ModuleSP module_sp) { + auto *sections = module_sp->GetSectionList(); + if (!sections) + return; + + auto summaries_sp = + sections->FindSectionByType(eSectionTypeLLDBTypeSummaries, true); + if (!summaries_sp) + return; + + Log *log = GetLog(LLDBLog::DataFormatters); + const char *module_name = module_sp->GetObjectName().GetCString(); + + TypeCategoryImplSP category; + DataVisualization::Categories::GetCategory(ConstString("default"), category); + + // The type summary record is serialized as follows. + // + // Each record contains, in order: + // * Version number of the record format + // * The remaining size of the record + // * The size of the type identifier + // * The type identifier, either a type name, or a regex + // * The size of the summary string + // * The summary string + // + // Integers are encoded using ULEB. + // + // Strings are encoded with first a length (ULEB), then the string contents, + // and lastly a null terminator. The length includes the null. + + DataExtractor extractor; + auto section_size = summaries_sp->GetSectionData(extractor); + lldb::offset_t offset = 0; + while (offset < section_size) { + uint64_t version = extractor.GetULEB128(&offset); + uint64_t record_size = extractor.GetULEB128(&offset); + if (version == 1) { + uint64_t type_size = extractor.GetULEB128(&offset); + llvm::StringRef type_name = extractor.GetCStr(&offset, type_size); + uint64_t summary_size = extractor.GetULEB128(&offset); + llvm::StringRef summary_string = extractor.GetCStr(&offset, summary_size); + if (!type_name.empty() && !summary_string.empty()) { + TypeSummaryImpl::Flags flags; + auto summary_sp = + std::make_shared<StringSummaryFormat>(flags, summary_string.data()); + FormatterMatchType match_type = eFormatterMatchExact; + if (summary_string.front() == '^' && summary_string.back() == '$') + match_type = eFormatterMatchRegex; + category->AddTypeSummary(type_name, match_type, summary_sp); + LLDB_LOGF(log, "Loaded embedded type summary for '%s' from %s.", + type_name.data(), module_name); + } else { + if (type_name.empty()) + LLDB_LOGF(log, "Missing string(s) in embedded type summary in %s.", + module_name); + } + } else { + // Skip unsupported record. + offset += record_size; + LLDB_LOGF( + log, + "Skipping unsupported embedded type summary of version %llu in %s.", + version, module_name); + } + } +} + void Target::ClearModules(bool delete_locations) { ModulesDidUnload(m_images, delete_locations); m_section_load_history.Clear(); @@ -1818,7 +1892,6 @@ void Target::ModulesDidLoad(ModuleList &module_list) { ModuleSP module_sp(module_list.GetModuleAtIndex(idx)); LoadScriptingResourceForModule(module_sp, this); LoadTypeSummariesForModule(module_sp); - LoadFormattersForModule(module_sp); } m_breakpoint_list.UpdateBreakpoints(module_list, true, false); m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false); diff --git a/lldb/test/API/functionalities/data-formatter/bytecode-summary/Makefile b/lldb/test/API/functionalities/data-formatter/bytecode-summary/Makefile deleted file mode 100644 index c9319d6e6888a4..00000000000000 --- a/lldb/test/API/functionalities/data-formatter/bytecode-summary/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -C_SOURCES := main.c -include Makefile.rules diff --git a/lldb/test/API/functionalities/data-formatter/bytecode-summary/TestBytecodeSummary.py b/lldb/test/API/functionalities/data-formatter/bytecode-summary/TestBytecodeSummary.py deleted file mode 100644 index 2b27bd3cdcda71..00000000000000 --- a/lldb/test/API/functionalities/data-formatter/bytecode-summary/TestBytecodeSummary.py +++ /dev/null @@ -1,17 +0,0 @@ -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - - -class TestCase(TestBase): - @skipUnlessDarwin - def test(self): - self.build() - if self.TraceOn(): - self.expect("log enable -v lldb formatters") - lldbutil.run_to_source_breakpoint( - self, "break here", lldb.SBFileSpec("main.cpp") - ) - self.expect("v x", substrs=["(MyOptional<int>) x = None"]) - self.expect("v y", substrs=["(MyOptional<int>) y = 42"]) diff --git a/lldb/test/API/functionalities/data-formatter/bytecode-summary/main.cpp b/lldb/test/API/functionalities/data-formatter/bytecode-summary/main.cpp deleted file mode 100644 index 35406acd6d0c4e..00000000000000 --- a/lldb/test/API/functionalities/data-formatter/bytecode-summary/main.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// A bare-bones llvm::Optional reimplementation. - -template <typename T> struct MyOptionalStorage { - MyOptionalStorage(T val) : value(val), hasVal(true) {} - MyOptionalStorage() {} - T value; - bool hasVal = false; -}; - -template <typename T> struct MyOptional { - MyOptionalStorage<T> Storage; - MyOptional(T val) : Storage(val) {} - MyOptional() {} - T &operator*() { return Storage.value; } -}; - -void stop() {} - -int main(int argc, char **argv) { - MyOptional<int> x, y = 42; - stop(); // break here - return *y; -} - -// Produced from the assembler in -// Shell/ScriptInterpreter/Python/Inputs/FormatterBytecode/formatter.py -__attribute__((used, section("__DATA_CONST,__lldbformatters"))) unsigned char - _MyOptional_type_summary[] = - "\x01" // version - "\xa4" // record size - "\x01" // record size - "\x10" // type name size - "^MyOptional<.+>$" // type name - "\x00" // flags - "\x00" // sig_summary - "\x8d" // program size - "\x01" // program size - "\x1\x22\x7Storage#\x12\x60\x1,C\x10\x1\x5\x11\x2\x1\x22\x6hasVal#" - "\x12\x60\x1,\x10\x1e\x2\x22\x1b<could not read MyOptional>\x10G#!\x60 " - "\x0P\x10\x6\x22\x4None\x10\x36\x1#\x15\x60 " - "\x0#\x16\x60\x5\x22\x5value#\x12\x60\x5#\x17\x60\x1," - "\x10\x6\x22\x4None\x10\x11\x1#\x0\x60\x1#R\x60\x10\x3# " - "\x60\x10\x1\x2\x12\x12\x12\x12"; // summary function diff --git a/lldb/unittests/DataFormatter/CMakeLists.txt b/lldb/unittests/DataFormatter/CMakeLists.txt index b858db1c716347..9d967a72bfd1fa 100644 --- a/lldb/unittests/DataFormatter/CMakeLists.txt +++ b/lldb/unittests/DataFormatter/CMakeLists.txt @@ -1,7 +1,6 @@ add_lldb_unittest(LLDBFormatterTests FormatManagerTests.cpp FormattersContainerTest.cpp - FormatterBytecodeTest.cpp StringPrinterTests.cpp LINK_LIBS diff --git a/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp b/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp deleted file mode 100644 index 15d9229de00332..00000000000000 --- a/lldb/unittests/DataFormatter/FormatterBytecodeTest.cpp +++ /dev/null @@ -1,261 +0,0 @@ -#include "DataFormatters/FormatterBytecode.h" -#include "lldb/Utility/StreamString.h" - -#include "gtest/gtest.h" - -using namespace lldb_private; -using namespace lldb; -using namespace FormatterBytecode; -using llvm::StringRef; - -namespace { -class FormatterBytecodeTest : public ::testing::Test {}; - -bool Interpret(std::vector<uint8_t> code, DataStack &data) { - auto buf = - StringRef(reinterpret_cast<const char *>(code.data()), code.size()); - std::vector<ControlStackElement> control({buf}); - if (auto error = Interpret(control, data, sel_summary)) { -#ifndef NDEBUG - llvm::errs() << llvm::toString(std::move(error)) << '\n'; -#else - llvm::consumeError(std::move(error)); -#endif - return false; - } - return true; -} - -} // namespace - -TEST_F(FormatterBytecodeTest, StackOps) { - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 23, op_dup, op_plus}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 46u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_drop}, data)); - ASSERT_EQ(data.size(), 0u); - } - { - for (unsigned char i = 0; i < 3; ++i) { - DataStack data; - - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lit_uint, 2, - op_lit_uint, i, op_pick}, - data)); - ASSERT_EQ(data.Pop<uint64_t>(), i); - } - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_over}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_swap}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - } - { - DataStack data; - ASSERT_TRUE(Interpret( - {op_lit_uint, 0, op_lit_uint, 1, op_lit_uint, 2, op_rot}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_EQ(data.Pop<uint64_t>(), 2u); - } -} - -TEST_F(FormatterBytecodeTest, ControlOps) { - { - DataStack data; - ASSERT_TRUE( - Interpret({op_lit_uint, 0, op_begin, 2, op_lit_uint, 42, op_if}, data)); - ASSERT_EQ(data.size(), 0u); - } - { - DataStack data; - ASSERT_TRUE( - Interpret({op_lit_uint, 1, op_begin, 2, op_lit_uint, 42, op_if}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 42u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_begin, 2, op_lit_uint, 42, - op_begin, 2, op_lit_uint, 23, op_ifelse}, - data)); - ASSERT_EQ(data.Pop<uint64_t>(), 23u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_begin, 2, op_lit_uint, 42, - op_begin, 2, op_lit_uint, 23, op_ifelse}, - data)); - ASSERT_EQ(data.Pop<uint64_t>(), 42u); - } - { - DataStack data(lldb::ValueObjectSP{}); - ASSERT_TRUE(Interpret({op_is_null}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 1u, op_as_int}, data)); - ASSERT_EQ(data.Pop<int64_t>(), 1); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_int, 126, op_as_uint}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), ~1ULL); - } -} - -TEST_F(FormatterBytecodeTest, ArithOps) { - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 2, op_lit_uint, 3, op_plus}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 5u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_minus}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_mul}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 6u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 6, op_lit_uint, 2, op_div}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 3u); - } - { - DataStack data; - ASSERT_FALSE(Interpret({op_lit_uint, 23, op_lit_uint, 0, op_div}, data)); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 2, op_shl}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 4u); - } - { - DataStack data; - unsigned char minus_one = 127; - ASSERT_TRUE( - Interpret({op_lit_int, minus_one, op_lit_uint, 2, op_shl}, data)); - ASSERT_EQ(data.Pop<int64_t>(), -4); - } - { - DataStack data; - ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shl}, data)); - ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shr}, data)); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_and}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_and}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_or}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_or}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_or}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_xor}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_xor}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_xor}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_not}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0xffffffffffffffff); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_eq}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_eq}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_neq}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_neq}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lt}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_lt}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_lt}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_gt}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_gt}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_gt}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_le}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_le}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_le}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - } - { - DataStack data; - ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_ge}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 0u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_ge}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_ge}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 1u); - } -} - -TEST_F(FormatterBytecodeTest, CallOps) { - { - DataStack data; - data.Push(std::string{"hello"}); - ASSERT_TRUE(Interpret({op_lit_selector, sel_strlen, op_call}, data)); - ASSERT_EQ(data.Pop<uint64_t>(), 5u); - } - { - DataStack data; - data.Push(std::string{"A"}); - data.Push(std::string{"B"}); - data.Push(std::string{"{1}{0}"}); - ASSERT_TRUE(Interpret({op_lit_selector, sel_fmt, op_call}, data)); - ASSERT_EQ(data.Pop<std::string>(), "BA"); - } - { - DataStack data; - data.Push(std::string{"{0}"}); - ASSERT_FALSE(Interpret({op_lit_selector, sel_fmt, op_call}, data)); - } -} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits