155 lines · cpp
1//===-- ManualDWARFIndex.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 "Plugins/SymbolFile/DWARF/ManualDWARFIndexSet.h"10#include "lldb/Core/DataFileCache.h"11#include "lldb/Utility/DataEncoder.h"12#include "lldb/Utility/DataExtractor.h"13#include <cstdint>14 15using namespace lldb_private;16using namespace lldb_private::plugin::dwarf;17 18namespace {19// Define IDs for the different tables when encoding and decoding the20// ManualDWARFIndex NameToDIE objects so we can avoid saving any empty maps.21enum DataID {22 kDataIDFunctionBasenames = 1u,23 kDataIDFunctionFullnames,24 kDataIDFunctionMethods,25 kDataIDFunctionSelectors,26 kDataIDFunctionObjcClassSelectors,27 kDataIDGlobals,28 kDataIDTypes,29 kDataIDNamespaces,30 kDataIDEnd = 255u,31};32} // namespace33 34// Version 2 changes the encoding of DIERef objects used in the DWARF manual35// index name tables. See DIERef class for details.36static constexpr uint32_t CURRENT_CACHE_VERSION = 2;37 38static constexpr llvm::StringLiteral kIdentifierManualDWARFIndex("DIDX");39 40std::optional<IndexSet<NameToDIE>>41plugin::dwarf::DecodeIndexSet(const DataExtractor &data,42 lldb::offset_t *offset_ptr) {43 StringTableReader strtab;44 // We now decode the string table for all strings in the data cache file.45 if (!strtab.Decode(data, offset_ptr))46 return std::nullopt;47 48 llvm::StringRef identifier((const char *)data.GetData(offset_ptr, 4), 4);49 if (identifier != kIdentifierManualDWARFIndex)50 return std::nullopt;51 const uint32_t version = data.GetU32(offset_ptr);52 if (version != CURRENT_CACHE_VERSION)53 return std::nullopt;54 55 IndexSet<NameToDIE> result;56 while (true) {57 switch (data.GetU8(offset_ptr)) {58 default:59 // If we got here, this is not expected, we expect the data IDs to match60 // one of the values from the DataID enumeration.61 return std::nullopt;62 case kDataIDFunctionBasenames:63 if (!result.function_basenames.Decode(data, offset_ptr, strtab))64 return std::nullopt;65 break;66 case kDataIDFunctionFullnames:67 if (!result.function_fullnames.Decode(data, offset_ptr, strtab))68 return std::nullopt;69 break;70 case kDataIDFunctionMethods:71 if (!result.function_methods.Decode(data, offset_ptr, strtab))72 return std::nullopt;73 break;74 case kDataIDFunctionSelectors:75 if (!result.function_selectors.Decode(data, offset_ptr, strtab))76 return std::nullopt;77 break;78 case kDataIDFunctionObjcClassSelectors:79 if (!result.objc_class_selectors.Decode(data, offset_ptr, strtab))80 return std::nullopt;81 break;82 case kDataIDGlobals:83 if (!result.globals.Decode(data, offset_ptr, strtab))84 return std::nullopt;85 break;86 case kDataIDTypes:87 if (!result.types.Decode(data, offset_ptr, strtab))88 return std::nullopt;89 break;90 case kDataIDNamespaces:91 if (!result.namespaces.Decode(data, offset_ptr, strtab))92 return std::nullopt;93 break;94 case kDataIDEnd:95 // We got to the end of our NameToDIE encodings.96 return std::move(result);97 break;98 }99 }100}101 102void plugin::dwarf::EncodeIndexSet(const IndexSet<NameToDIE> &set,103 DataEncoder &encoder) {104 ConstStringTable strtab;105 106 // Encoder the DWARF index into a separate encoder first. This allows us107 // gather all of the strings we willl need in "strtab" as we will need to108 // write the string table out before the symbol table.109 DataEncoder index_encoder(encoder.GetByteOrder(),110 encoder.GetAddressByteSize());111 112 index_encoder.AppendData(kIdentifierManualDWARFIndex);113 // Encode the data version.114 index_encoder.AppendU32(CURRENT_CACHE_VERSION);115 116 if (!set.function_basenames.IsEmpty()) {117 index_encoder.AppendU8(kDataIDFunctionBasenames);118 set.function_basenames.Encode(index_encoder, strtab);119 }120 if (!set.function_fullnames.IsEmpty()) {121 index_encoder.AppendU8(kDataIDFunctionFullnames);122 set.function_fullnames.Encode(index_encoder, strtab);123 }124 if (!set.function_methods.IsEmpty()) {125 index_encoder.AppendU8(kDataIDFunctionMethods);126 set.function_methods.Encode(index_encoder, strtab);127 }128 if (!set.function_selectors.IsEmpty()) {129 index_encoder.AppendU8(kDataIDFunctionSelectors);130 set.function_selectors.Encode(index_encoder, strtab);131 }132 if (!set.objc_class_selectors.IsEmpty()) {133 index_encoder.AppendU8(kDataIDFunctionObjcClassSelectors);134 set.objc_class_selectors.Encode(index_encoder, strtab);135 }136 if (!set.globals.IsEmpty()) {137 index_encoder.AppendU8(kDataIDGlobals);138 set.globals.Encode(index_encoder, strtab);139 }140 if (!set.types.IsEmpty()) {141 index_encoder.AppendU8(kDataIDTypes);142 set.types.Encode(index_encoder, strtab);143 }144 if (!set.namespaces.IsEmpty()) {145 index_encoder.AppendU8(kDataIDNamespaces);146 set.namespaces.Encode(index_encoder, strtab);147 }148 index_encoder.AppendU8(kDataIDEnd);149 150 // Now that all strings have been gathered, we will emit the string table.151 strtab.Encode(encoder);152 // Followed by the symbol table data.153 encoder.AppendData(index_encoder.GetData());154}155