1 //===-- TestObjectFileELF.cpp ---------------------------------------------===// 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/SubsystemRAII.h" 13 #include "TestingSupport/TestUtilities.h" 14 #include "lldb/Core/Module.h" 15 #include "lldb/Core/ModuleSpec.h" 16 #include "lldb/Core/Section.h" 17 #include "lldb/Host/FileSystem.h" 18 #include "lldb/Host/HostInfo.h" 19 #include "lldb/Utility/DataBufferHeap.h" 20 #include "llvm/ADT/Optional.h" 21 #include "llvm/Support/Compression.h" 22 #include "llvm/Support/FileUtilities.h" 23 #include "llvm/Support/Path.h" 24 #include "llvm/Support/Program.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include "llvm/Testing/Support/Error.h" 27 #include "gtest/gtest.h" 28 29 using namespace lldb_private; 30 using namespace lldb; 31 32 class ObjectFileELFTest : public testing::Test { 33 SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab> 34 subsystems; 35 }; 36 37 TEST_F(ObjectFileELFTest, SectionsResolveConsistently) { 38 auto ExpectedFile = TestFile::fromYaml(R"( 39 --- !ELF 40 FileHeader: 41 Class: ELFCLASS64 42 Data: ELFDATA2LSB 43 Type: ET_EXEC 44 Machine: EM_X86_64 45 Entry: 0x0000000000400180 46 Sections: 47 - Name: .note.gnu.build-id 48 Type: SHT_NOTE 49 Flags: [ SHF_ALLOC ] 50 Address: 0x0000000000400158 51 AddressAlign: 0x0000000000000004 52 Content: 040000001400000003000000474E55003F3EC29E3FD83E49D18C4D49CD8A730CC13117B6 53 - Name: .text 54 Type: SHT_PROGBITS 55 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 56 Address: 0x0000000000400180 57 AddressAlign: 0x0000000000000010 58 Content: 554889E58B042500106000890425041060005DC3 59 - Name: .data 60 Type: SHT_PROGBITS 61 Flags: [ SHF_WRITE, SHF_ALLOC ] 62 Address: 0x0000000000601000 63 AddressAlign: 0x0000000000000004 64 Content: 2F000000 65 - Name: .bss 66 Type: SHT_NOBITS 67 Flags: [ SHF_WRITE, SHF_ALLOC ] 68 Address: 0x0000000000601004 69 AddressAlign: 0x0000000000000004 70 Size: 0x0000000000000004 71 Symbols: 72 - Name: Y 73 Type: STT_OBJECT 74 Section: .data 75 Value: 0x0000000000601000 76 Size: 0x0000000000000004 77 Binding: STB_GLOBAL 78 - Name: _start 79 Type: STT_FUNC 80 Section: .text 81 Value: 0x0000000000400180 82 Size: 0x0000000000000014 83 Binding: STB_GLOBAL 84 - Name: X 85 Type: STT_OBJECT 86 Section: .bss 87 Value: 0x0000000000601004 88 Size: 0x0000000000000004 89 Binding: STB_GLOBAL 90 ... 91 )"); 92 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); 93 94 auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec()); 95 SectionList *list = module_sp->GetSectionList(); 96 ASSERT_NE(nullptr, list); 97 98 auto bss_sp = list->FindSectionByName(ConstString(".bss")); 99 ASSERT_NE(nullptr, bss_sp); 100 auto data_sp = list->FindSectionByName(ConstString(".data")); 101 ASSERT_NE(nullptr, data_sp); 102 auto text_sp = list->FindSectionByName(ConstString(".text")); 103 ASSERT_NE(nullptr, text_sp); 104 105 const Symbol *X = module_sp->FindFirstSymbolWithNameAndType(ConstString("X"), 106 eSymbolTypeAny); 107 ASSERT_NE(nullptr, X); 108 EXPECT_EQ(bss_sp, X->GetAddress().GetSection()); 109 110 const Symbol *Y = module_sp->FindFirstSymbolWithNameAndType(ConstString("Y"), 111 eSymbolTypeAny); 112 ASSERT_NE(nullptr, Y); 113 EXPECT_EQ(data_sp, Y->GetAddress().GetSection()); 114 115 const Symbol *start = module_sp->FindFirstSymbolWithNameAndType( 116 ConstString("_start"), eSymbolTypeAny); 117 ASSERT_NE(nullptr, start); 118 EXPECT_EQ(text_sp, start->GetAddress().GetSection()); 119 } 120 121 // Test that GetModuleSpecifications works on an "atypical" object file which 122 // has section headers right after the ELF header (instead of the more common 123 // layout where the section headers are at the very end of the object file). 124 // 125 // Test file generated with yaml2obj (@svn rev 324254) from the following input: 126 /* 127 --- !ELF 128 FileHeader: 129 Class: ELFCLASS64 130 Data: ELFDATA2LSB 131 Type: ET_EXEC 132 Machine: EM_X86_64 133 Entry: 0x00000000004003D0 134 Sections: 135 - Name: .note.gnu.build-id 136 Type: SHT_NOTE 137 Flags: [ SHF_ALLOC ] 138 Address: 0x0000000000400274 139 AddressAlign: 0x0000000000000004 140 Content: 040000001400000003000000474E55001B8A73AC238390E32A7FF4AC8EBE4D6A41ECF5C9 141 - Name: .text 142 Type: SHT_PROGBITS 143 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 144 Address: 0x00000000004003D0 145 AddressAlign: 0x0000000000000010 146 Content: DEADBEEFBAADF00D 147 ... 148 */ 149 TEST_F(ObjectFileELFTest, GetModuleSpecifications_EarlySectionHeaders) { 150 std::string SO = GetInputFilePath("early-section-headers.so"); 151 ModuleSpecList Specs; 152 ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 0, 0, Specs)); 153 ModuleSpec Spec; 154 ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ; 155 UUID Uuid; 156 Uuid.SetFromStringRef("1b8a73ac238390e32a7ff4ac8ebe4d6a41ecf5c9"); 157 EXPECT_EQ(Spec.GetUUID(), Uuid); 158 } 159 160 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmThumbAddressClass) { 161 /* 162 // nosym-entrypoint-arm-thumb.s 163 .thumb_func 164 _start: 165 mov r0, #42 166 mov r7, #1 167 svc #0 168 // arm-linux-androideabi-as nosym-entrypoint-arm-thumb.s 169 // -o nosym-entrypoint-arm-thumb.o 170 // arm-linux-androideabi-ld nosym-entrypoint-arm-thumb.o 171 // -o nosym-entrypoint-arm-thumb -e 0x8075 -s 172 */ 173 auto ExpectedFile = TestFile::fromYaml(R"( 174 --- !ELF 175 FileHeader: 176 Class: ELFCLASS32 177 Data: ELFDATA2LSB 178 Type: ET_EXEC 179 Machine: EM_ARM 180 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ] 181 Entry: 0x0000000000008075 182 Sections: 183 - Name: .text 184 Type: SHT_PROGBITS 185 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 186 Address: 0x0000000000008074 187 AddressAlign: 0x0000000000000002 188 Content: 2A20012700DF 189 - Name: .data 190 Type: SHT_PROGBITS 191 Flags: [ SHF_WRITE, SHF_ALLOC ] 192 Address: 0x0000000000009000 193 AddressAlign: 0x0000000000000001 194 Content: '' 195 - Name: .bss 196 Type: SHT_NOBITS 197 Flags: [ SHF_WRITE, SHF_ALLOC ] 198 Address: 0x0000000000009000 199 AddressAlign: 0x0000000000000001 200 - Name: .note.gnu.gold-version 201 Type: SHT_NOTE 202 AddressAlign: 0x0000000000000004 203 Content: 040000000900000004000000474E5500676F6C6420312E3131000000 204 - Name: .ARM.attributes 205 Type: SHT_ARM_ATTRIBUTES 206 AddressAlign: 0x0000000000000001 207 Content: '4113000000616561626900010900000006020901' 208 ... 209 )"); 210 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); 211 212 auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec()); 213 214 auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress(); 215 ASSERT_TRUE(entry_point_addr.GetOffset() & 1); 216 // Decrease the offsite by 1 to make it into a breakable address since this 217 // is Thumb. 218 entry_point_addr.SetOffset(entry_point_addr.GetOffset() - 1); 219 ASSERT_EQ(entry_point_addr.GetAddressClass(), 220 AddressClass::eCodeAlternateISA); 221 } 222 223 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmAddressClass) { 224 /* 225 // nosym-entrypoint-arm.s 226 _start: 227 movs r0, #42 228 movs r7, #1 229 svc #0 230 // arm-linux-androideabi-as nosym-entrypoint-arm.s 231 // -o nosym-entrypoint-arm.o 232 // arm-linux-androideabi-ld nosym-entrypoint-arm.o 233 // -o nosym-entrypoint-arm -e 0x8074 -s 234 */ 235 auto ExpectedFile = TestFile::fromYaml(R"( 236 --- !ELF 237 FileHeader: 238 Class: ELFCLASS32 239 Data: ELFDATA2LSB 240 Type: ET_EXEC 241 Machine: EM_ARM 242 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ] 243 Entry: 0x0000000000008074 244 Sections: 245 - Name: .text 246 Type: SHT_PROGBITS 247 Flags: [ SHF_ALLOC, SHF_EXECINSTR ] 248 Address: 0x0000000000008074 249 AddressAlign: 0x0000000000000004 250 Content: 2A00A0E30170A0E3000000EF 251 - Name: .data 252 Type: SHT_PROGBITS 253 Flags: [ SHF_WRITE, SHF_ALLOC ] 254 Address: 0x0000000000009000 255 AddressAlign: 0x0000000000000001 256 Content: '' 257 - Name: .bss 258 Type: SHT_NOBITS 259 Flags: [ SHF_WRITE, SHF_ALLOC ] 260 Address: 0x0000000000009000 261 AddressAlign: 0x0000000000000001 262 - Name: .note.gnu.gold-version 263 Type: SHT_NOTE 264 AddressAlign: 0x0000000000000004 265 Content: 040000000900000004000000474E5500676F6C6420312E3131000000 266 - Name: .ARM.attributes 267 Type: SHT_ARM_ATTRIBUTES 268 AddressAlign: 0x0000000000000001 269 Content: '4113000000616561626900010900000006010801' 270 ... 271 )"); 272 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded()); 273 274 auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec()); 275 276 auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress(); 277 ASSERT_EQ(entry_point_addr.GetAddressClass(), AddressClass::eCode); 278 } 279