1 //===-- TestObjectFileELF.cpp -----------------------------------*- C++ -*-===// 2 // 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h" 11 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h" 12 #include "TestingSupport/TestUtilities.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/ModuleSpec.h" 15 #include "lldb/Core/Section.h" 16 #include "lldb/Host/FileSystem.h" 17 #include "lldb/Host/HostInfo.h" 18 #include "lldb/Utility/DataBufferHeap.h" 19 #include "llvm/ADT/Optional.h" 20 #include "llvm/Support/Compression.h" 21 #include "llvm/Support/FileUtilities.h" 22 #include "llvm/Support/Path.h" 23 #include "llvm/Support/Program.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include "llvm/Testing/Support/Error.h" 26 #include "gtest/gtest.h" 27 28 using namespace lldb_private; 29 using namespace lldb; 30 31 class ObjectFileELFTest : public testing::Test { 32 public: 33 void SetUp() override { 34 FileSystem::Initialize(); 35 HostInfo::Initialize(); 36 ObjectFileELF::Initialize(); 37 SymbolFileSymtab::Initialize(); 38 } 39 40 void TearDown() override { 41 SymbolFileSymtab::Terminate(); 42 ObjectFileELF::Terminate(); 43 HostInfo::Terminate(); 44 FileSystem::Terminate(); 45 } 46 47 protected: 48 }; 49 50 TEST_F(ObjectFileELFTest, SectionsResolveConsistently) { 51 auto ExpectedFile = TestFile::fromYaml(R"( 52 --- !ELF 53 FileHeader: 54 Class: ELFCLASS64 55 Data: ELFDATA2LSB 56 Type: ET_EXEC 57 Machine: EM_X86_64 58 Entry: 0x0000000000400180 59 Sections: 60 - Name: .note.gnu.build-id 61 Type: SHT_NOTE 62 Flags: [ SHF_ALLOC ] 63 Address: 0x0000000000400158 64 AddressAlign: 0x0000000000000004 65 Content: 040000001400000003000000474E55003F3EC29E3FD83E49D18C4D49CD8A730CC13117B6 66 - Name: .text 67 Type: SHT_PROGBITS 68 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 69 Address: 0x0000000000400180 70 AddressAlign: 0x0000000000000010 71 Content: 554889E58B042500106000890425041060005DC3 72 - Name: .data 73 Type: SHT_PROGBITS 74 Flags: [ SHF_WRITE, SHF_ALLOC ] 75 Address: 0x0000000000601000 76 AddressAlign: 0x0000000000000004 77 Content: 2F000000 78 - Name: .bss 79 Type: SHT_NOBITS 80 Flags: [ SHF_WRITE, SHF_ALLOC ] 81 Address: 0x0000000000601004 82 AddressAlign: 0x0000000000000004 83 Size: 0x0000000000000004 84 Symbols: 85 - Name: Y 86 Type: STT_OBJECT 87 Section: .data 88 Value: 0x0000000000601000 89 Size: 0x0000000000000004 90 Binding: STB_GLOBAL 91 - Name: _start 92 Type: STT_FUNC 93 Section: .text 94 Value: 0x0000000000400180 95 Size: 0x0000000000000014 96 Binding: STB_GLOBAL 97 - Name: X 98 Type: STT_OBJECT 99 Section: .bss 100 Value: 0x0000000000601004 101 Size: 0x0000000000000004 102 Binding: STB_GLOBAL 103 ... 104 )"); 105 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); 106 107 ModuleSpec spec{FileSpec(ExpectedFile->name())}; 108 spec.GetSymbolFileSpec().SetFile(ExpectedFile->name(), 109 FileSpec::Style::native); 110 auto module_sp = std::make_shared<Module>(spec); 111 SectionList *list = module_sp->GetSectionList(); 112 ASSERT_NE(nullptr, list); 113 114 auto bss_sp = list->FindSectionByName(ConstString(".bss")); 115 ASSERT_NE(nullptr, bss_sp); 116 auto data_sp = list->FindSectionByName(ConstString(".data")); 117 ASSERT_NE(nullptr, data_sp); 118 auto text_sp = list->FindSectionByName(ConstString(".text")); 119 ASSERT_NE(nullptr, text_sp); 120 121 const Symbol *X = module_sp->FindFirstSymbolWithNameAndType(ConstString("X"), 122 eSymbolTypeAny); 123 ASSERT_NE(nullptr, X); 124 EXPECT_EQ(bss_sp, X->GetAddress().GetSection()); 125 126 const Symbol *Y = module_sp->FindFirstSymbolWithNameAndType(ConstString("Y"), 127 eSymbolTypeAny); 128 ASSERT_NE(nullptr, Y); 129 EXPECT_EQ(data_sp, Y->GetAddress().GetSection()); 130 131 const Symbol *start = module_sp->FindFirstSymbolWithNameAndType( 132 ConstString("_start"), eSymbolTypeAny); 133 ASSERT_NE(nullptr, start); 134 EXPECT_EQ(text_sp, start->GetAddress().GetSection()); 135 } 136 137 // Test that GetModuleSpecifications works on an "atypical" object file which 138 // has section headers right after the ELF header (instead of the more common 139 // layout where the section headers are at the very end of the object file). 140 // 141 // Test file generated with yaml2obj (@svn rev 324254) from the following input: 142 /* 143 --- !ELF 144 FileHeader: 145 Class: ELFCLASS64 146 Data: ELFDATA2LSB 147 Type: ET_EXEC 148 Machine: EM_X86_64 149 Entry: 0x00000000004003D0 150 Sections: 151 - Name: .note.gnu.build-id 152 Type: SHT_NOTE 153 Flags: [ SHF_ALLOC ] 154 Address: 0x0000000000400274 155 AddressAlign: 0x0000000000000004 156 Content: 040000001400000003000000474E55001B8A73AC238390E32A7FF4AC8EBE4D6A41ECF5C9 157 - Name: .text 158 Type: SHT_PROGBITS 159 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 160 Address: 0x00000000004003D0 161 AddressAlign: 0x0000000000000010 162 Content: DEADBEEFBAADF00D 163 ... 164 */ 165 TEST_F(ObjectFileELFTest, GetModuleSpecifications_EarlySectionHeaders) { 166 std::string SO = GetInputFilePath("early-section-headers.so"); 167 ModuleSpecList Specs; 168 ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 0, 0, Specs)); 169 ModuleSpec Spec; 170 ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ; 171 UUID Uuid; 172 Uuid.SetFromStringRef("1b8a73ac238390e32a7ff4ac8ebe4d6a41ecf5c9", 20); 173 EXPECT_EQ(Spec.GetUUID(), Uuid); 174 } 175