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