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-exception 6 // 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 14 using namespace lldb; 15 16 namespace lldb_private { 17 static 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 format 35 // * The remaining size of the record 36 // * The size of the type identifier 37 // * The type identifier, either a type name, or a regex 38 // * The size of the entry 39 // * The entry 40 // 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 else 74 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 89 void 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 string 99 // * The summary string 100 // 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 131 void 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 bytecode 138 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 } else 164 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_private 171