#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);
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) {
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 {
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);
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) {
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());
}
});
}
}