brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.2 KiB · 31cf949 Raw
291 lines · cpp
1//===-- DWARFIndexCachingTest.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/DIERef.h"10#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"11#include "Plugins/SymbolFile/DWARF/ManualDWARFIndexSet.h"12#include "Plugins/SymbolFile/DWARF/NameToDIE.h"13#include "TestingSupport/Symbol/YAMLModuleTester.h"14#include "lldb/Core/DataFileCache.h"15#include "lldb/Core/ModuleList.h"16#include "lldb/Utility/DataEncoder.h"17#include "lldb/Utility/DataExtractor.h"18#include "llvm/ADT/STLExtras.h"19#include "gmock/gmock.h"20#include "gtest/gtest.h"21 22using namespace lldb;23using namespace lldb_private;24using namespace lldb_private::plugin::dwarf;25 26static void EncodeDecode(const DIERef &object, ByteOrder byte_order) {27  const uint8_t addr_size = 8;28  DataEncoder encoder(byte_order, addr_size);29  object.Encode(encoder);30  llvm::ArrayRef<uint8_t> bytes = encoder.GetData();31  DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);32  offset_t data_offset = 0;33  EXPECT_EQ(object, DIERef::Decode(data, &data_offset));34}35 36static void EncodeDecode(const DIERef &object) {37  EncodeDecode(object, eByteOrderLittle);38  EncodeDecode(object, eByteOrderBig);39}40 41TEST(DWARFIndexCachingTest, DIERefEncodeDecode) {42  // Tests DIERef::Encode(...) and DIERef::Decode(...)43  EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugInfo, 0x11223344));44  EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugTypes, 0x11223344));45  EncodeDecode(DIERef(100, DIERef::Section::DebugInfo, 0x11223344));46  EncodeDecode(DIERef(200, DIERef::Section::DebugTypes, 0x11223344));47}48 49TEST(DWARFIndexCachingTest, DIERefEncodeDecodeMax) {50  // Tests DIERef::Encode(...) and DIERef::Decode(...)51  EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugInfo,52                      DIERef::k_die_offset_mask - 1));53  EncodeDecode(DIERef(std::nullopt, DIERef::Section::DebugTypes,54                      DIERef::k_die_offset_mask - 1));55  EncodeDecode(56      DIERef(100, DIERef::Section::DebugInfo, DIERef::k_die_offset_mask - 1));57  EncodeDecode(58      DIERef(200, DIERef::Section::DebugTypes, DIERef::k_die_offset_mask - 1));59  EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugInfo,60                      DIERef::k_file_index_mask));61  EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugTypes,62                      DIERef::k_file_index_mask));63  EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugInfo,64                      0x11223344));65  EncodeDecode(DIERef(DIERef::k_file_index_mask, DIERef::Section::DebugTypes,66                      0x11223344));67}68 69static void EncodeDecode(const NameToDIE &object, ByteOrder byte_order) {70  const uint8_t addr_size = 8;71  DataEncoder encoder(byte_order, addr_size);72  DataEncoder strtab_encoder(byte_order, addr_size);73  ConstStringTable const_strtab;74 75  object.Encode(encoder, const_strtab);76 77  llvm::ArrayRef<uint8_t> bytes = encoder.GetData();78  DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);79 80  const_strtab.Encode(strtab_encoder);81  llvm::ArrayRef<uint8_t> strtab_bytes = strtab_encoder.GetData();82  DataExtractor strtab_data(strtab_bytes.data(), strtab_bytes.size(),83                            byte_order, addr_size);84  StringTableReader strtab_reader;85  offset_t strtab_data_offset = 0;86  ASSERT_EQ(strtab_reader.Decode(strtab_data, &strtab_data_offset), true);87 88  NameToDIE decoded_object;89  offset_t data_offset = 0;90  decoded_object.Decode(data, &data_offset, strtab_reader);91  EXPECT_EQ(object, decoded_object);92}93 94static void EncodeDecode(const NameToDIE &object) {95  EncodeDecode(object, eByteOrderLittle);96  EncodeDecode(object, eByteOrderBig);97}98 99TEST(DWARFIndexCachingTest, NameToDIEEncodeDecode) {100  NameToDIE map;101  // Make sure an empty NameToDIE map encodes and decodes correctly.102  EncodeDecode(map);103  map.Insert(ConstString("hello"),104             DIERef(std::nullopt, DIERef::Section::DebugInfo, 0x11223344));105  map.Insert(ConstString("workd"),106             DIERef(100, DIERef::Section::DebugInfo, 0x11223344));107  map.Finalize();108  // Make sure a valid NameToDIE map encodes and decodes correctly.109  EncodeDecode(map);110}111 112static void EncodeDecode(const IndexSet<NameToDIE> &object,113                         ByteOrder byte_order) {114  const uint8_t addr_size = 8;115  DataEncoder encoder(byte_order, addr_size);116  DataEncoder strtab_encoder(byte_order, addr_size);117  EncodeIndexSet(object, encoder);118  llvm::ArrayRef<uint8_t> bytes = encoder.GetData();119  DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);120  offset_t data_offset = 0;121  EXPECT_EQ(DecodeIndexSet(data, &data_offset), object);122}123 124static void EncodeDecode(const IndexSet<NameToDIE> &object) {125  EncodeDecode(object, eByteOrderLittle);126  EncodeDecode(object, eByteOrderBig);127}128 129TEST(DWARFIndexCachingTest, ManualDWARFIndexIndexSetEncodeDecode) {130  IndexSet<NameToDIE> set;131  // Make sure empty IndexSet can be encoded and decoded correctly132  EncodeDecode(set);133 134  dw_offset_t die_offset = 0;135  // Make sure an IndexSet with only items in IndexSet::function_basenames can136  // be encoded and decoded correctly.137  set.function_basenames.Insert(138      ConstString("a"),139      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));140  EncodeDecode(set);141  set.function_basenames.Clear();142  // Make sure an IndexSet with only items in IndexSet::function_fullnames can143  // be encoded and decoded correctly.144  set.function_fullnames.Insert(145      ConstString("a"),146      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));147  EncodeDecode(set);148  set.function_fullnames.Clear();149  // Make sure an IndexSet with only items in IndexSet::function_methods can150  // be encoded and decoded correctly.151  set.function_methods.Insert(152      ConstString("a"),153      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));154  EncodeDecode(set);155  set.function_methods.Clear();156  // Make sure an IndexSet with only items in IndexSet::function_selectors can157  // be encoded and decoded correctly.158  set.function_selectors.Insert(159      ConstString("a"),160      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));161  EncodeDecode(set);162  set.function_selectors.Clear();163  // Make sure an IndexSet with only items in IndexSet::objc_class_selectors can164  // be encoded and decoded correctly.165  set.objc_class_selectors.Insert(166      ConstString("a"),167      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));168  EncodeDecode(set);169  set.objc_class_selectors.Clear();170  // Make sure an IndexSet with only items in IndexSet::globals can171  // be encoded and decoded correctly.172  set.globals.Insert(173      ConstString("a"),174      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));175  EncodeDecode(set);176  set.globals.Clear();177  // Make sure an IndexSet with only items in IndexSet::types can178  // be encoded and decoded correctly.179  set.types.Insert(180      ConstString("a"),181      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));182  EncodeDecode(set);183  set.types.Clear();184  // Make sure an IndexSet with only items in IndexSet::namespaces can185  // be encoded and decoded correctly.186  set.namespaces.Insert(187      ConstString("a"),188      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));189  EncodeDecode(set);190  set.namespaces.Clear();191  // Make sure that an IndexSet with item in all NameToDIE maps can be192  // be encoded and decoded correctly.193  set.function_basenames.Insert(194      ConstString("a"),195      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));196  set.function_fullnames.Insert(197      ConstString("b"),198      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));199  set.function_methods.Insert(200      ConstString("c"),201      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));202  set.function_selectors.Insert(203      ConstString("d"),204      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));205  set.objc_class_selectors.Insert(206      ConstString("e"),207      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));208  set.globals.Insert(209      ConstString("f"),210      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));211  set.types.Insert(212      ConstString("g"),213      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));214  set.namespaces.Insert(215      ConstString("h"),216      DIERef(std::nullopt, DIERef::Section::DebugInfo, ++die_offset));217  EncodeDecode(set);218}219 220static void EncodeDecode(const CacheSignature &object, ByteOrder byte_order,221                         bool encode_result) {222  const uint8_t addr_size = 8;223  DataEncoder encoder(byte_order, addr_size);224  EXPECT_EQ(encode_result, object.Encode(encoder));225  if (!encode_result)226    return;227  llvm::ArrayRef<uint8_t> bytes = encoder.GetData();228  DataExtractor data(bytes.data(), bytes.size(), byte_order, addr_size);229  offset_t data_offset = 0;230  CacheSignature decoded_object;231  EXPECT_TRUE(decoded_object.Decode(data, &data_offset));232  EXPECT_EQ(object, decoded_object);233}234 235static void EncodeDecode(const CacheSignature &object, bool encode_result) {236  EncodeDecode(object, eByteOrderLittle, encode_result);237  EncodeDecode(object, eByteOrderBig, encode_result);238}239 240TEST(DWARFIndexCachingTest, CacheSignatureTests) {241  CacheSignature sig;242  // A cache signature is only considered valid if it has a UUID.243  sig.m_mod_time = 0x12345678;244  EXPECT_FALSE(sig.IsValid());245  EncodeDecode(sig, /*encode_result=*/false);246  sig.Clear();247 248  sig.m_obj_mod_time = 0x12345678;249  EXPECT_FALSE(sig.IsValid());250  EncodeDecode(sig, /*encode_result=*/false);251  sig.Clear();252 253  sig.m_uuid = UUID("@\x00\x11\x22\x33\x44\x55\x66\x77", 8);254  EXPECT_TRUE(sig.IsValid());255  EncodeDecode(sig, /*encode_result=*/true);256  sig.m_mod_time = 0x12345678;257  EXPECT_TRUE(sig.IsValid());258  EncodeDecode(sig, /*encode_result=*/true);259  sig.m_obj_mod_time = 0x456789ab;260  EXPECT_TRUE(sig.IsValid());261  EncodeDecode(sig, /*encode_result=*/true);262  sig.m_mod_time = std::nullopt;263  EXPECT_TRUE(sig.IsValid());264  EncodeDecode(sig, /*encode_result=*/true);265 266  // Recent changes do not allow cache signatures with only a modification time267  // or object modification time, so make sure if we try to decode such a cache268  // file that we fail. This verifies that if we try to load an previously269  // valid cache file where the signature is insufficient, that we will fail to270  // decode and load these cache files.271  DataEncoder encoder(eByteOrderLittle, /*addr_size=*/8);272  encoder.AppendU8(2); // eSignatureModTime273  encoder.AppendU32(0x12345678);274  encoder.AppendU8(255); // eSignatureEnd275 276  llvm::ArrayRef<uint8_t> bytes = encoder.GetData();277  DataExtractor data(bytes.data(), bytes.size(), eByteOrderLittle,278                     /*addr_size=*/8);279  offset_t data_offset = 0;280 281  // Make sure we fail to decode a CacheSignature with only a mod time282  EXPECT_FALSE(sig.Decode(data, &data_offset));283 284  // Change the signature data to contain only a eSignatureObjectModTime and285  // make sure decoding fails as well.286  encoder.PutU8(/*offset=*/0, 3); // eSignatureObjectModTime287  data_offset = 0;288  EXPECT_FALSE(sig.Decode(data, &data_offset));289 290}291