171 lines
6.8 KiB
C++
171 lines
6.8 KiB
C++
//===-- 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
|