summaryrefslogtreecommitdiff
path: root/lldb/source/DataFormatters/FormatterSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/DataFormatters/FormatterSection.cpp')
-rw-r--r--lldb/source/DataFormatters/FormatterSection.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/lldb/source/DataFormatters/FormatterSection.cpp b/lldb/source/DataFormatters/FormatterSection.cpp
new file mode 100644
index 000000000000..1de633f4998e
--- /dev/null
+++ b/lldb/source/DataFormatters/FormatterSection.cpp
@@ -0,0 +1,170 @@
+//===-- 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) {
+ while (cursor && cursor.tell() < section_size) {
+ // Skip over 0 padding.
+ if (section.getU8(cursor) == 0)
+ continue;
+ cursor.seek(cursor.tell() - 1);
+ break;
+ }
+ 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