1 //===-- TestObjectFileELF.cpp ---------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
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"
28 using namespace lldb_private
;
31 class ObjectFileELFTest
: public testing::Test
{
32 SubsystemRAII
<FileSystem
, HostInfo
, ObjectFileELF
, SymbolFileSymtab
>
36 TEST_F(ObjectFileELFTest
, SectionsResolveConsistently
) {
37 auto ExpectedFile
= TestFile::fromYaml(R
"(
44 Entry: 0x0000000000400180
46 - Name: .note.gnu.build-id
49 Address: 0x0000000000400158
50 AddressAlign: 0x0000000000000004
51 Content: 040000001400000003000000474E55003F3EC29E3FD83E49D18C4D49CD8A730CC13117B6
54 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
55 Address: 0x0000000000400180
56 AddressAlign: 0x0000000000000010
57 Content: 554889E58B042500106000890425041060005DC3
60 Flags: [ SHF_WRITE, SHF_ALLOC ]
61 Address: 0x0000000000601000
62 AddressAlign: 0x0000000000000004
66 Flags: [ SHF_WRITE, SHF_ALLOC ]
67 Address: 0x0000000000601004
68 AddressAlign: 0x0000000000000004
69 Size: 0x0000000000000004
74 Value: 0x0000000000601000
75 Size: 0x0000000000000004
80 Value: 0x0000000000400180
81 Size: 0x0000000000000014
86 Value: 0x0000000000601004
87 Size: 0x0000000000000004
91 ASSERT_THAT_EXPECTED(ExpectedFile
, llvm::Succeeded());
93 auto module_sp
= std::make_shared
<Module
>(ExpectedFile
->moduleSpec());
94 SectionList
*list
= module_sp
->GetSectionList();
95 ASSERT_NE(nullptr, list
);
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
);
104 const Symbol
*X
= module_sp
->FindFirstSymbolWithNameAndType(ConstString("X"),
106 ASSERT_NE(nullptr, X
);
107 EXPECT_EQ(bss_sp
, X
->GetAddress().GetSection());
109 const Symbol
*Y
= module_sp
->FindFirstSymbolWithNameAndType(ConstString("Y"),
111 ASSERT_NE(nullptr, Y
);
112 EXPECT_EQ(data_sp
, Y
->GetAddress().GetSection());
114 const Symbol
*start
= module_sp
->FindFirstSymbolWithNameAndType(
115 ConstString("_start"), eSymbolTypeAny
);
116 ASSERT_NE(nullptr, start
);
117 EXPECT_EQ(text_sp
, start
->GetAddress().GetSection());
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).
124 // Test file generated with yaml2obj (@svn rev 324254) from the following input:
132 Entry: 0x00000000004003D0
134 - Name: .note.gnu.build-id
137 Address: 0x0000000000400274
138 AddressAlign: 0x0000000000000004
139 Content: 040000001400000003000000474E55001B8A73AC238390E32A7FF4AC8EBE4D6A41ECF5C9
142 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
143 Address: 0x00000000004003D0
144 AddressAlign: 0x0000000000000010
145 Content: DEADBEEFBAADF00D
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
));
153 ASSERT_TRUE(Specs
.GetModuleSpecAtIndex(0, Spec
)) ;
155 Uuid
.SetFromStringRef("1b8a73ac238390e32a7ff4ac8ebe4d6a41ecf5c9");
156 EXPECT_EQ(Spec
.GetUUID(), Uuid
);
159 TEST_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
));
164 ASSERT_TRUE(Specs
.GetModuleSpecAtIndex(0, Spec
)) ;
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);
173 TEST_F(ObjectFileELFTest
, GetModuleSpecifications_OffsetSizeWithOffsetFile
) {
174 // The contents of offset-test.bin are
176 // - 1024-4623: liboffset-test.so (offset: 1024, size: 3600, CRC32: 7D6E4738)
178 std::string SO
= GetInputFilePath("offset-test.bin");
179 ModuleSpecList Specs
;
181 1u, ObjectFile::GetModuleSpecifications(FileSpec(SO
), 1024, 3600, Specs
));
183 ASSERT_TRUE(Specs
.GetModuleSpecAtIndex(0, Spec
)) ;
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);
192 TEST_F(ObjectFileELFTest
, GetSymtab_NoSymEntryPointArmThumbAddressClass
) {
194 // nosym-entrypoint-arm-thumb.s
200 // arm-linux-androideabi-as nosym-entrypoint-arm-thumb.s
201 // -o nosym-entrypoint-arm-thumb.o
202 // arm-linux-androideabi-ld nosym-entrypoint-arm-thumb.o
203 // -o nosym-entrypoint-arm-thumb -e 0x8075 -s
205 auto ExpectedFile
= TestFile::fromYaml(R
"(
212 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
213 Entry: 0x0000000000008075
217 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
218 Address: 0x0000000000008074
219 AddressAlign: 0x0000000000000002
220 Content: 2A20012700DF
223 Flags: [ SHF_WRITE, SHF_ALLOC ]
224 Address: 0x0000000000009000
225 AddressAlign: 0x0000000000000001
229 Flags: [ SHF_WRITE, SHF_ALLOC ]
230 Address: 0x0000000000009000
231 AddressAlign: 0x0000000000000001
232 - Name: .note.gnu.gold-version
234 AddressAlign: 0x0000000000000004
235 Content: 040000000900000004000000474E5500676F6C6420312E3131000000
236 - Name: .ARM.attributes
237 Type: SHT_ARM_ATTRIBUTES
238 AddressAlign: 0x0000000000000001
239 Content: '4113000000616561626900010900000006020901'
242 ASSERT_THAT_EXPECTED(ExpectedFile
, llvm::Succeeded());
244 auto module_sp
= std::make_shared
<Module
>(ExpectedFile
->moduleSpec());
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 this
250 entry_point_addr
.SetOffset(entry_point_addr
.GetOffset() - 1);
251 ASSERT_EQ(entry_point_addr
.GetAddressClass(),
252 AddressClass::eCodeAlternateISA
);
255 TEST_F(ObjectFileELFTest
, GetSymtab_NoSymEntryPointArmAddressClass
) {
257 // nosym-entrypoint-arm.s
262 // arm-linux-androideabi-as nosym-entrypoint-arm.s
263 // -o nosym-entrypoint-arm.o
264 // arm-linux-androideabi-ld nosym-entrypoint-arm.o
265 // -o nosym-entrypoint-arm -e 0x8074 -s
267 auto ExpectedFile
= TestFile::fromYaml(R
"(
274 Flags: [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
275 Entry: 0x0000000000008074
279 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
280 Address: 0x0000000000008074
281 AddressAlign: 0x0000000000000004
282 Content: 2A00A0E30170A0E3000000EF
285 Flags: [ SHF_WRITE, SHF_ALLOC ]
286 Address: 0x0000000000009000
287 AddressAlign: 0x0000000000000001
291 Flags: [ SHF_WRITE, SHF_ALLOC ]
292 Address: 0x0000000000009000
293 AddressAlign: 0x0000000000000001
294 - Name: .note.gnu.gold-version
296 AddressAlign: 0x0000000000000004
297 Content: 040000000900000004000000474E5500676F6C6420312E3131000000
298 - Name: .ARM.attributes
299 Type: SHT_ARM_ATTRIBUTES
300 AddressAlign: 0x0000000000000001
301 Content: '4113000000616561626900010900000006010801'
304 ASSERT_THAT_EXPECTED(ExpectedFile
, llvm::Succeeded());
306 auto module_sp
= std::make_shared
<Module
>(ExpectedFile
->moduleSpec());
308 auto entry_point_addr
= module_sp
->GetObjectFile()->GetEntryPointAddress();
309 ASSERT_EQ(entry_point_addr
.GetAddressClass(), AddressClass::eCode
);