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 176 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmThumbAddressClass) { 177 /* 178 // nosym-entrypoint-arm-thumb.s 179 .thumb_func 180 _start: 181 mov r0, #42 182 mov r7, #1 183 svc #0 184 // arm-linux-androideabi-as nosym-entrypoint-arm-thumb.s 185 // -o nosym-entrypoint-arm-thumb.o 186 // arm-linux-androideabi-ld nosym-entrypoint-arm-thumb.o 187 // -o nosym-entrypoint-arm-thumb -e 0x8075 -s 188 */ 189 auto ExpectedFile = TestFile::fromYaml(R"( 190 --- !ELF 191 FileHeader: 192 Class: ELFCLASS32 193 Data: ELFDATA2LSB 194 Type: ET_EXEC 195 Machine: EM_ARM 196 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ] 197 Entry: 0x0000000000008075 198 Sections: 199 - Name: .text 200 Type: SHT_PROGBITS 201 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 202 Address: 0x0000000000008074 203 AddressAlign: 0x0000000000000002 204 Content: 2A20012700DF 205 - Name: .data 206 Type: SHT_PROGBITS 207 Flags: [ SHF_WRITE, SHF_ALLOC ] 208 Address: 0x0000000000009000 209 AddressAlign: 0x0000000000000001 210 Content: '' 211 - Name: .bss 212 Type: SHT_NOBITS 213 Flags: [ SHF_WRITE, SHF_ALLOC ] 214 Address: 0x0000000000009000 215 AddressAlign: 0x0000000000000001 216 - Name: .note.gnu.gold-version 217 Type: SHT_NOTE 218 AddressAlign: 0x0000000000000004 219 Content: 040000000900000004000000474E5500676F6C6420312E3131000000 220 - Name: .ARM.attributes 221 Type: SHT_ARM_ATTRIBUTES 222 AddressAlign: 0x0000000000000001 223 Content: '4113000000616561626900010900000006020901' 224 ... 225 )"); 226 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); 227 228 ModuleSpec spec{FileSpec(ExpectedFile->name())}; 229 spec.GetSymbolFileSpec().SetFile(ExpectedFile->name(), 230 FileSpec::Style::native); 231 auto module_sp = std::make_shared<Module>(spec); 232 233 auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress(); 234 ASSERT_TRUE(entry_point_addr.GetOffset() & 1); 235 // Decrease the offsite by 1 to make it into a breakable address since this 236 // is Thumb. 237 entry_point_addr.SetOffset(entry_point_addr.GetOffset() - 1); 238 ASSERT_EQ(entry_point_addr.GetAddressClass(), 239 AddressClass::eCodeAlternateISA); 240 } 241 242 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmAddressClass) { 243 /* 244 // nosym-entrypoint-arm.s 245 _start: 246 movs r0, #42 247 movs r7, #1 248 svc #0 249 // arm-linux-androideabi-as nosym-entrypoint-arm.s 250 // -o nosym-entrypoint-arm.o 251 // arm-linux-androideabi-ld nosym-entrypoint-arm.o 252 // -o nosym-entrypoint-arm -e 0x8074 -s 253 */ 254 auto ExpectedFile = TestFile::fromYaml(R"( 255 --- !ELF 256 FileHeader: 257 Class: ELFCLASS32 258 Data: ELFDATA2LSB 259 Type: ET_EXEC 260 Machine: EM_ARM 261 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ] 262 Entry: 0x0000000000008074 263 Sections: 264 - Name: .text 265 Type: SHT_PROGBITS 266 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 267 Address: 0x0000000000008074 268 AddressAlign: 0x0000000000000004 269 Content: 2A00A0E30170A0E3000000EF 270 - Name: .data 271 Type: SHT_PROGBITS 272 Flags: [ SHF_WRITE, SHF_ALLOC ] 273 Address: 0x0000000000009000 274 AddressAlign: 0x0000000000000001 275 Content: '' 276 - Name: .bss 277 Type: SHT_NOBITS 278 Flags: [ SHF_WRITE, SHF_ALLOC ] 279 Address: 0x0000000000009000 280 AddressAlign: 0x0000000000000001 281 - Name: .note.gnu.gold-version 282 Type: SHT_NOTE 283 AddressAlign: 0x0000000000000004 284 Content: 040000000900000004000000474E5500676F6C6420312E3131000000 285 - Name: .ARM.attributes 286 Type: SHT_ARM_ATTRIBUTES 287 AddressAlign: 0x0000000000000001 288 Content: '4113000000616561626900010900000006010801' 289 ... 290 )"); 291 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); 292 293 ModuleSpec spec{FileSpec(ExpectedFile->name())}; 294 spec.GetSymbolFileSpec().SetFile(ExpectedFile->name(), 295 FileSpec::Style::native); 296 auto module_sp = std::make_shared<Module>(spec); 297 298 auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress(); 299 ASSERT_EQ(entry_point_addr.GetAddressClass(), AddressClass::eCode); 300 }