mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
Compared to the python version, this also does type checking and error handling, so it's slightly longer, however, it's still comfortably under 500 lines. Relanding with more explicit type conversions.
164 lines
6.6 KiB
C++
164 lines
6.6 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) {
|
|
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
|