llvm-project/lldb/source/DataFormatters/FormatterSection.cpp

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