Path: blob/main/contrib/llvm-project/lldb/source/DataFormatters/FormatterSection.cpp
213764 views
//===-- FormatterBytecode.cpp ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "FormatterBytecode.h"9#include "lldb/Core/Module.h"10#include "lldb/DataFormatters/DataVisualization.h"11#include "lldb/Utility/LLDBLog.h"1213using namespace lldb;1415namespace lldb_private {16static void ForEachFormatterInModule(17Module &module, SectionType section_type,18std::function<void(llvm::DataExtractor, llvm::StringRef)> fn) {19auto *sections = module.GetSectionList();20if (!sections)21return;2223auto section_sp = sections->FindSectionByType(section_type, true);24if (!section_sp)25return;2627TypeCategoryImplSP category;28DataVisualization::Categories::GetCategory(ConstString("default"), category);2930// The type summary record is serialized as follows.31//32// Each record contains, in order:33// * Version number of the record format34// * The remaining size of the record35// * The size of the type identifier36// * The type identifier, either a type name, or a regex37// * The size of the entry38// * The entry39//40// Integers are encoded using ULEB.41//42// Strings are encoded with first a length (ULEB), then the string contents,43// and lastly a null terminator. The length includes the null.4445DataExtractor lldb_extractor;46auto section_size = section_sp->GetSectionData(lldb_extractor);47llvm::DataExtractor section = lldb_extractor.GetAsLLVM();48bool le = section.isLittleEndian();49uint8_t addr_size = section.getAddressSize();50llvm::DataExtractor::Cursor cursor(0);51while (cursor && cursor.tell() < section_size) {52while (cursor && cursor.tell() < section_size) {53// Skip over 0 padding.54if (section.getU8(cursor) == 0)55continue;56cursor.seek(cursor.tell() - 1);57break;58}59uint64_t version = section.getULEB128(cursor);60uint64_t record_size = section.getULEB128(cursor);61if (version == 1) {62llvm::DataExtractor record(section.getData().drop_front(cursor.tell()),63le, addr_size);64llvm::DataExtractor::Cursor cursor(0);65uint64_t type_size = record.getULEB128(cursor);66llvm::StringRef type_name = record.getBytes(cursor, type_size);67llvm::Error error = cursor.takeError();68if (!error)69fn(llvm::DataExtractor(record.getData().drop_front(cursor.tell()), le,70addr_size),71type_name);72else73LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), std::move(error),74"{0}");75} else {76// Skip unsupported record.77LLDB_LOG(78GetLog(LLDBLog::DataFormatters),79"Skipping unsupported embedded type summary of version {0} in {1}.",80version, module.GetFileSpec());81}82section.skip(cursor, record_size);83}84if (!cursor)85LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(), "{0}");86}8788void LoadTypeSummariesForModule(ModuleSP module_sp) {89ForEachFormatterInModule(90*module_sp, eSectionTypeLLDBTypeSummaries,91[&](llvm::DataExtractor extractor, llvm::StringRef type_name) {92TypeCategoryImplSP category;93DataVisualization::Categories::GetCategory(ConstString("default"),94category);95// The type summary record is serialized as follows.96//97// * The size of the summary string98// * The summary string99//100// Integers are encoded using ULEB.101llvm::DataExtractor::Cursor cursor(0);102uint64_t summary_size = extractor.getULEB128(cursor);103llvm::StringRef summary_string =104extractor.getBytes(cursor, summary_size);105if (!cursor) {106LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(),107"{0}");108return;109}110if (type_name.empty() || summary_string.empty()) {111LLDB_LOG(GetLog(LLDBLog::DataFormatters),112"Missing string(s) in embedded type summary in {0}, "113"type_name={1}, summary={2}",114module_sp->GetFileSpec(), type_name, summary_string);115return;116}117TypeSummaryImpl::Flags flags;118auto summary_sp = std::make_shared<StringSummaryFormat>(119flags, summary_string.str().c_str());120FormatterMatchType match_type = eFormatterMatchExact;121if (type_name.front() == '^')122match_type = eFormatterMatchRegex;123category->AddTypeSummary(type_name, match_type, summary_sp);124LLDB_LOG(GetLog(LLDBLog::DataFormatters),125"Loaded embedded type summary for '{0}' from {1}.", type_name,126module_sp->GetFileSpec());127});128}129130void LoadFormattersForModule(ModuleSP module_sp) {131ForEachFormatterInModule(132*module_sp, eSectionTypeLLDBFormatters,133[&](llvm::DataExtractor extractor, llvm::StringRef type_name) {134// * Function signature (1 byte)135// * Length of the program (ULEB128)136// * The program bytecode137TypeCategoryImplSP category;138DataVisualization::Categories::GetCategory(ConstString("default"),139category);140llvm::DataExtractor::Cursor cursor(0);141uint64_t flags = extractor.getULEB128(cursor);142while (cursor && cursor.tell() < extractor.size()) {143uint8_t signature = extractor.getU8(cursor);144uint64_t size = extractor.getULEB128(cursor);145llvm::StringRef bytecode = extractor.getBytes(cursor, size);146if (!cursor) {147LLDB_LOG_ERROR(GetLog(LLDBLog::DataFormatters), cursor.takeError(),148"{0}");149return;150}151if (signature == 0) {152auto summary_sp = std::make_shared<BytecodeSummaryFormat>(153TypeSummaryImpl::Flags(flags),154llvm::MemoryBuffer::getMemBufferCopy(bytecode));155FormatterMatchType match_type = eFormatterMatchExact;156if (type_name.front() == '^')157match_type = eFormatterMatchRegex;158category->AddTypeSummary(type_name, match_type, summary_sp);159LLDB_LOG(GetLog(LLDBLog::DataFormatters),160"Loaded embedded type summary for '{0}' from {1}.",161type_name, module_sp->GetFileSpec());162} else163LLDB_LOG(GetLog(LLDBLog::DataFormatters),164"Unsupported formatter signature {0} for '{1}' in {2}",165signature, type_name, module_sp->GetFileSpec());166}167});168}169} // namespace lldb_private170171172