1 //===----------------------- ELFTypesTest.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 #include "llvm/Object/ELFTypes.h" 9 #include "llvm/Testing/Support/Error.h" 10 #include "gtest/gtest.h" 11 #include <iostream> 12 13 using namespace llvm; 14 using namespace llvm::object; 15 16 template <typename ELFT> using Elf_Note = typename ELFT::Note; 17 18 template <class ELFT> struct NoteTestData { 19 std::vector<uint8_t> Data; 20 21 const Elf_Note_Impl<ELFT> getElfNote(StringRef Name, uint32_t Type, 22 ArrayRef<uint8_t> Desc) { 23 constexpr uint64_t Align = 4; 24 Data.resize(alignTo(sizeof(Elf_Nhdr_Impl<ELFT>) + Name.size(), Align) + 25 alignTo(Desc.size(), Align), 26 0); 27 28 Elf_Nhdr_Impl<ELFT> *Nhdr = 29 reinterpret_cast<Elf_Nhdr_Impl<ELFT> *>(Data.data()); 30 Nhdr->n_namesz = (Name == "") ? 0 : Name.size() + 1; 31 Nhdr->n_descsz = Desc.size(); 32 Nhdr->n_type = Type; 33 34 auto NameOffset = Data.begin() + sizeof(*Nhdr); 35 std::copy(Name.begin(), Name.end(), NameOffset); 36 37 auto DescOffset = 38 Data.begin() + alignTo(sizeof(*Nhdr) + Nhdr->n_namesz, Align); 39 std::copy(Desc.begin(), Desc.end(), DescOffset); 40 41 return Elf_Note_Impl<ELFT>(*Nhdr); 42 } 43 }; 44 45 TEST(ELFTypesTest, NoteTest) { 46 static const uint8_t Random[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 47 ArrayRef<uint8_t> RandomData = ArrayRef(Random); 48 NoteTestData<ELF64LE> TestData; 49 50 auto Note1 = TestData.getElfNote(StringRef("AMD"), ELF::NT_AMDGPU_METADATA, 51 RandomData); 52 EXPECT_EQ(Note1.getName(), "AMD"); 53 EXPECT_EQ(Note1.getType(), ELF::NT_AMDGPU_METADATA); 54 EXPECT_EQ(Note1.getDesc(4), RandomData); 55 EXPECT_EQ(Note1.getDescAsStringRef(4), 56 StringRef(reinterpret_cast<const char *>(Random), sizeof(Random))); 57 58 auto Note2 = TestData.getElfNote("", ELF::NT_AMDGPU_METADATA, RandomData); 59 EXPECT_EQ(Note2.getName(), ""); 60 61 auto Note3 = 62 TestData.getElfNote("AMD", ELF::NT_AMDGPU_METADATA, ArrayRef<uint8_t>()); 63 EXPECT_EQ(Note3.getDescAsStringRef(4), StringRef("")); 64 } 65 66 TEST(ELFTypesTest, BBEntryMetadataEncodingTest) { 67 const std::array<BBAddrMap::BBEntry::Metadata, 7> Decoded = { 68 {{false, false, false, false, false}, 69 {true, false, false, false, false}, 70 {false, true, false, false, false}, 71 {false, false, true, false, false}, 72 {false, false, false, true, false}, 73 {false, false, false, false, true}, 74 {true, true, true, true, true}}}; 75 const std::array<uint32_t, 7> Encoded = {{0, 1, 2, 4, 8, 16, 31}}; 76 for (size_t i = 0; i < Decoded.size(); ++i) 77 EXPECT_EQ(Decoded[i].encode(), Encoded[i]); 78 for (size_t i = 0; i < Encoded.size(); ++i) { 79 Expected<BBAddrMap::BBEntry::Metadata> MetadataOrError = 80 BBAddrMap::BBEntry::Metadata::decode(Encoded[i]); 81 ASSERT_THAT_EXPECTED(MetadataOrError, Succeeded()); 82 EXPECT_EQ(*MetadataOrError, Decoded[i]); 83 } 84 } 85 86 TEST(ELFTypesTest, BBEntryMetadataInvalidEncodingTest) { 87 const std::array<std::string, 2> Errors = { 88 "invalid encoding for BBEntry::Metadata: 0xffff", 89 "invalid encoding for BBEntry::Metadata: 0x100001"}; 90 const std::array<uint32_t, 2> Values = {{0xFFFF, 0x100001}}; 91 for (size_t i = 0; i < Values.size(); ++i) { 92 EXPECT_THAT_ERROR( 93 BBAddrMap::BBEntry::Metadata::decode(Values[i]).takeError(), 94 FailedWithMessage(Errors[i])); 95 } 96 } 97 98 static_assert( 99 std::is_same_v<decltype(PGOAnalysisMap::PGOBBEntry::SuccessorEntry::ID), 100 decltype(BBAddrMap::BBEntry::ID)>, 101 "PGOAnalysisMap should use the same type for basic block ID as BBAddrMap"); 102 103 TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) { 104 const std::array<BBAddrMap::Features, 9> Decoded = { 105 {{false, false, false, false, false}, 106 {true, false, false, false, false}, 107 {false, true, false, false, false}, 108 {false, false, true, false, false}, 109 {false, false, false, true, false}, 110 {true, true, false, false, false}, 111 {false, true, true, false, false}, 112 {false, true, true, true, false}, 113 {true, true, true, true, false}}}; 114 const std::array<uint8_t, 9> Encoded = { 115 {0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111}}; 116 for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) 117 EXPECT_EQ(Feat.encode(), EncodedVal); 118 for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) { 119 Expected<BBAddrMap::Features> FeatEnableOrError = 120 BBAddrMap::Features::decode(EncodedVal); 121 ASSERT_THAT_EXPECTED(FeatEnableOrError, Succeeded()); 122 EXPECT_EQ(*FeatEnableOrError, Feat); 123 } 124 } 125 126 TEST(ELFTypesTest, BBAddrMapFeaturesInvalidEncodingTest) { 127 const std::array<std::string, 2> Errors = { 128 "invalid encoding for BBAddrMap::Features: 0x20", 129 "invalid encoding for BBAddrMap::Features: 0xf0"}; 130 const std::array<uint8_t, 2> Values = {{0b10'0000, 0b1111'0000}}; 131 for (const auto &[Val, Error] : llvm::zip(Values, Errors)) { 132 EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(), 133 FailedWithMessage(Error)); 134 } 135 } 136