1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 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
|