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