392 lines · cpp
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-exception7//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 28using namespace lldb_private;29using namespace lldb;30 31class ObjectFileELFTest : public testing::Test {32 SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, SymbolFileSymtab>33 subsystems;34};35 36TEST_F(ObjectFileELFTest, SectionsResolveConsistently) {37 auto ExpectedFile = TestFile::fromYaml(R"(38--- !ELF39FileHeader:40 Class: ELFCLASS6441 Data: ELFDATA2LSB42 Type: ET_EXEC43 Machine: EM_X86_6444 Entry: 0x000000000040018045Sections:46 - Name: .note.gnu.build-id47 Type: SHT_NOTE48 Flags: [ SHF_ALLOC ]49 Address: 0x000000000040015850 AddressAlign: 0x000000000000000451 Content: 040000001400000003000000474E55003F3EC29E3FD83E49D18C4D49CD8A730CC13117B652 - Name: .text53 Type: SHT_PROGBITS54 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]55 Address: 0x000000000040018056 AddressAlign: 0x000000000000001057 Content: 554889E58B042500106000890425041060005DC358 - Name: .data59 Type: SHT_PROGBITS60 Flags: [ SHF_WRITE, SHF_ALLOC ]61 Address: 0x000000000060100062 AddressAlign: 0x000000000000000463 Content: 2F00000064 - Name: .bss65 Type: SHT_NOBITS66 Flags: [ SHF_WRITE, SHF_ALLOC ]67 Address: 0x000000000060100468 AddressAlign: 0x000000000000000469 Size: 0x000000000000000470Symbols:71 - Name: Y72 Type: STT_OBJECT73 Section: .data74 Value: 0x000000000060100075 Size: 0x000000000000000476 Binding: STB_GLOBAL77 - Name: _start78 Type: STT_FUNC79 Section: .text80 Value: 0x000000000040018081 Size: 0x000000000000001482 Binding: STB_GLOBAL83 - Name: X84 Type: STT_OBJECT85 Section: .bss86 Value: 0x000000000060100487 Size: 0x000000000000000488 Binding: STB_GLOBAL89...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 which121// has section headers right after the ELF header (instead of the more common122// 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--- !ELF127FileHeader:128 Class: ELFCLASS64129 Data: ELFDATA2LSB130 Type: ET_EXEC131 Machine: EM_X86_64132 Entry: 0x00000000004003D0133Sections:134 - Name: .note.gnu.build-id135 Type: SHT_NOTE136 Flags: [ SHF_ALLOC ]137 Address: 0x0000000000400274138 AddressAlign: 0x0000000000000004139 Content: 040000001400000003000000474E55001B8A73AC238390E32A7FF4AC8EBE4D6A41ECF5C9140 - Name: .text141 Type: SHT_PROGBITS142 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]143 Address: 0x00000000004003D0144 AddressAlign: 0x0000000000000010145 Content: DEADBEEFBAADF00D146...147*/148TEST_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 159TEST_F(ObjectFileELFTest, GetModuleSpecifications_OffsetSizeWithNormalFile) {160 std::string SO = GetInputFilePath("liboffset-test.so");161 ModuleSpecList Specs;162 ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 0, 0, Specs));163 ModuleSpec Spec;164 ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ;165 UUID Uuid;166 Uuid.SetFromStringRef("7D6E4738");167 EXPECT_EQ(Spec.GetUUID(), Uuid);168 EXPECT_EQ(Spec.GetObjectOffset(), 0UL);169 EXPECT_EQ(Spec.GetObjectSize(), 3600UL);170 EXPECT_EQ(FileSystem::Instance().GetByteSize(FileSpec(SO)), 3600UL);171}172 173TEST_F(ObjectFileELFTest, GetModuleSpecifications_OffsetSizeWithOffsetFile) {174 // The contents of offset-test.bin are175 // - 0-1023: \0176 // - 1024-4623: liboffset-test.so (offset: 1024, size: 3600, CRC32: 7D6E4738)177 // - 4624-4639: \0178 std::string SO = GetInputFilePath("offset-test.bin");179 ModuleSpecList Specs;180 ASSERT_EQ(181 1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 1024, 3600, Specs));182 ModuleSpec Spec;183 ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ;184 UUID Uuid;185 Uuid.SetFromStringRef("7D6E4738");186 EXPECT_EQ(Spec.GetUUID(), Uuid);187 EXPECT_EQ(Spec.GetObjectOffset(), 1024UL);188 EXPECT_EQ(Spec.GetObjectSize(), 3600UL);189 EXPECT_EQ(FileSystem::Instance().GetByteSize(FileSpec(SO)), 4640UL);190}191 192TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmThumbAddressClass) {193 /*194 // nosym-entrypoint-arm-thumb.s195 .thumb_func196 _start:197 mov r0, #42198 mov r7, #1199 svc #0200 // arm-linux-androideabi-as nosym-entrypoint-arm-thumb.s201 // -o nosym-entrypoint-arm-thumb.o202 // arm-linux-androideabi-ld nosym-entrypoint-arm-thumb.o203 // -o nosym-entrypoint-arm-thumb -e 0x8075 -s204 */205 auto ExpectedFile = TestFile::fromYaml(R"(206--- !ELF207FileHeader:208 Class: ELFCLASS32209 Data: ELFDATA2LSB210 Type: ET_EXEC211 Machine: EM_ARM212 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]213 Entry: 0x0000000000008075214Sections:215 - Name: .text216 Type: SHT_PROGBITS217 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]218 Address: 0x0000000000008074219 AddressAlign: 0x0000000000000002220 Content: 2A20012700DF221 - Name: .data222 Type: SHT_PROGBITS223 Flags: [ SHF_WRITE, SHF_ALLOC ]224 Address: 0x0000000000009000225 AddressAlign: 0x0000000000000001226 Content: ''227 - Name: .bss228 Type: SHT_NOBITS229 Flags: [ SHF_WRITE, SHF_ALLOC ]230 Address: 0x0000000000009000231 AddressAlign: 0x0000000000000001232 - Name: .note.gnu.gold-version233 Type: SHT_NOTE234 AddressAlign: 0x0000000000000004235 Content: 040000000900000004000000474E5500676F6C6420312E3131000000236 - Name: .ARM.attributes237 Type: SHT_ARM_ATTRIBUTES238 AddressAlign: 0x0000000000000001239 Content: '4113000000616561626900010900000006020901'240...241)");242 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());243 244 auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());245 246 auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress();247 ASSERT_TRUE(entry_point_addr.GetOffset() & 1);248 // Decrease the offsite by 1 to make it into a breakable address since this249 // is Thumb.250 entry_point_addr.SetOffset(entry_point_addr.GetOffset() - 1);251 ASSERT_EQ(entry_point_addr.GetAddressClass(),252 AddressClass::eCodeAlternateISA);253}254 255TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmAddressClass) {256 /*257 // nosym-entrypoint-arm.s258 _start:259 movs r0, #42260 movs r7, #1261 svc #0262 // arm-linux-androideabi-as nosym-entrypoint-arm.s263 // -o nosym-entrypoint-arm.o264 // arm-linux-androideabi-ld nosym-entrypoint-arm.o265 // -o nosym-entrypoint-arm -e 0x8074 -s266 */267 auto ExpectedFile = TestFile::fromYaml(R"(268--- !ELF269FileHeader:270 Class: ELFCLASS32271 Data: ELFDATA2LSB272 Type: ET_EXEC273 Machine: EM_ARM274 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]275 Entry: 0x0000000000008074276Sections:277 - Name: .text278 Type: SHT_PROGBITS279 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]280 Address: 0x0000000000008074281 AddressAlign: 0x0000000000000004282 Content: 2A00A0E30170A0E3000000EF283 - Name: .data284 Type: SHT_PROGBITS285 Flags: [ SHF_WRITE, SHF_ALLOC ]286 Address: 0x0000000000009000287 AddressAlign: 0x0000000000000001288 Content: ''289 - Name: .bss290 Type: SHT_NOBITS291 Flags: [ SHF_WRITE, SHF_ALLOC ]292 Address: 0x0000000000009000293 AddressAlign: 0x0000000000000001294 - Name: .note.gnu.gold-version295 Type: SHT_NOTE296 AddressAlign: 0x0000000000000004297 Content: 040000000900000004000000474E5500676F6C6420312E3131000000298 - Name: .ARM.attributes299 Type: SHT_ARM_ATTRIBUTES300 AddressAlign: 0x0000000000000001301 Content: '4113000000616561626900010900000006010801'302...303)");304 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());305 306 auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());307 308 auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress();309 ASSERT_EQ(entry_point_addr.GetAddressClass(), AddressClass::eCode);310}311 312TEST_F(ObjectFileELFTest, SkipsLocalMappingAndDotLSymbols) {313 auto ExpectedFile = TestFile::fromYaml(R"(314--- !ELF315 FileHeader:316 Class: ELFCLASS64317 Data: ELFDATA2LSB318 Type: ET_EXEC319 Machine: EM_RISCV320 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SINGLE ]321 Entry: 0xC0A1B010322 Sections:323 - Name: .text324 Type: SHT_PROGBITS325 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]326 Address: 0x0000000000400180327 AddressAlign: 0x0000000000000010328 Content: 554889E5329 - Name: .data330 Type: SHT_PROGBITS331 Flags: [ SHF_WRITE, SHF_ALLOC ]332 Address: 0x0000000000601000333 AddressAlign: 0x0000000000000004334 Content: 2F000000335 - Name: .riscv.attributes336 Type: SHT_PROGBITS337 Flags: [ SHF_ALLOC ]338 Address: 0x0000000000610000339 AddressAlign: 0x0000000000000004340 Content: "00"341 Symbols:342 - Name: $d343 Type: STT_NOTYPE344 Section: .riscv.attributes345 Value: 0x0000000000400180346 Size: 0x10347 Binding: STB_LOCAL348 - Name: $x349 Type: STT_NOTYPE350 Section: .text351 Value: 0xC0A1B010352 Size: 0x10353 Binding: STB_LOCAL354 - Name: .Lfoo355 Type: STT_OBJECT356 Section: .data357 Value: 0x0000000000601000358 Size: 0x4359 Binding: STB_LOCAL360 - Name: global_func361 Type: STT_FUNC362 Section: .text363 Value: 0x00000000004001A0364 Size: 0x10365 Binding: STB_GLOBAL366 - Name: global_obj367 Type: STT_OBJECT368 Section: .data369 Value: 0x0000000000601004370 Size: 0x4371 Binding: STB_GLOBAL372...373 )");374 ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());375 auto module_sp = std::make_shared<Module>(ExpectedFile->moduleSpec());376 auto *symtab = module_sp->GetSymtab();377 ASSERT_NE(nullptr, symtab);378 EXPECT_EQ(nullptr, module_sp->FindFirstSymbolWithNameAndType(379 ConstString("$d"), eSymbolTypeAny));380 EXPECT_EQ(nullptr, module_sp->FindFirstSymbolWithNameAndType(381 ConstString("$x"), eSymbolTypeAny));382 EXPECT_EQ(nullptr, module_sp->FindFirstSymbolWithNameAndType(383 ConstString(".Lfoo"), eSymbolTypeAny));384 // assert that other symbols are present385 const Symbol *global_func = module_sp->FindFirstSymbolWithNameAndType(386 ConstString("global_func"), eSymbolTypeAny);387 ASSERT_NE(nullptr, global_func);388 const Symbol *global_obj = module_sp->FindFirstSymbolWithNameAndType(389 ConstString("global_obj"), eSymbolTypeAny);390 ASSERT_NE(nullptr, global_obj);391}392