xref: /llvm-project/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp (revision b0b9605a544dbf26940a48777af401a419f4e4f1)
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 
TEST_F(ObjectFileELFTest,SectionsResolveConsistently)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 */
TEST_F(ObjectFileELFTest,GetModuleSpecifications_EarlySectionHeaders)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 
TEST_F(ObjectFileELFTest,GetModuleSpecifications_OffsetSizeWithNormalFile)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));
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 
TEST_F(ObjectFileELFTest,GetModuleSpecifications_OffsetSizeWithOffsetFile)173 TEST_F(ObjectFileELFTest, GetModuleSpecifications_OffsetSizeWithOffsetFile) {
174   // The contents of offset-test.bin are
175   // -    0-1023: \0
176   // - 1024-4623: liboffset-test.so (offset: 1024, size: 3600, CRC32: 7D6E4738)
177   // - 4624-4639: \0
178   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 
TEST_F(ObjectFileELFTest,GetSymtab_NoSymEntryPointArmThumbAddressClass)192 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmThumbAddressClass) {
193   /*
194   // nosym-entrypoint-arm-thumb.s
195   .thumb_func
196   _start:
197       mov r0, #42
198       mov r7, #1
199       svc #0
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
204   */
205   auto ExpectedFile = TestFile::fromYaml(R"(
206 --- !ELF
207 FileHeader:
208   Class:           ELFCLASS32
209   Data:            ELFDATA2LSB
210   Type:            ET_EXEC
211   Machine:         EM_ARM
212   Flags:           [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
213   Entry:           0x0000000000008075
214 Sections:
215   - Name:            .text
216     Type:            SHT_PROGBITS
217     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
218     Address:         0x0000000000008074
219     AddressAlign:    0x0000000000000002
220     Content:         2A20012700DF
221   - Name:            .data
222     Type:            SHT_PROGBITS
223     Flags:           [ SHF_WRITE, SHF_ALLOC ]
224     Address:         0x0000000000009000
225     AddressAlign:    0x0000000000000001
226     Content:         ''
227   - Name:            .bss
228     Type:            SHT_NOBITS
229     Flags:           [ SHF_WRITE, SHF_ALLOC ]
230     Address:         0x0000000000009000
231     AddressAlign:    0x0000000000000001
232   - Name:            .note.gnu.gold-version
233     Type:            SHT_NOTE
234     AddressAlign:    0x0000000000000004
235     Content:         040000000900000004000000474E5500676F6C6420312E3131000000
236   - Name:            .ARM.attributes
237     Type:            SHT_ARM_ATTRIBUTES
238     AddressAlign:    0x0000000000000001
239     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 this
249   // is Thumb.
250   entry_point_addr.SetOffset(entry_point_addr.GetOffset() - 1);
251   ASSERT_EQ(entry_point_addr.GetAddressClass(),
252             AddressClass::eCodeAlternateISA);
253 }
254 
TEST_F(ObjectFileELFTest,GetSymtab_NoSymEntryPointArmAddressClass)255 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmAddressClass) {
256   /*
257   // nosym-entrypoint-arm.s
258   _start:
259       movs r0, #42
260       movs r7, #1
261       svc #0
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
266   */
267   auto ExpectedFile = TestFile::fromYaml(R"(
268 --- !ELF
269 FileHeader:
270   Class:           ELFCLASS32
271   Data:            ELFDATA2LSB
272   Type:            ET_EXEC
273   Machine:         EM_ARM
274   Flags:           [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
275   Entry:           0x0000000000008074
276 Sections:
277   - Name:            .text
278     Type:            SHT_PROGBITS
279     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
280     Address:         0x0000000000008074
281     AddressAlign:    0x0000000000000004
282     Content:         2A00A0E30170A0E3000000EF
283   - Name:            .data
284     Type:            SHT_PROGBITS
285     Flags:           [ SHF_WRITE, SHF_ALLOC ]
286     Address:         0x0000000000009000
287     AddressAlign:    0x0000000000000001
288     Content:         ''
289   - Name:            .bss
290     Type:            SHT_NOBITS
291     Flags:           [ SHF_WRITE, SHF_ALLOC ]
292     Address:         0x0000000000009000
293     AddressAlign:    0x0000000000000001
294   - Name:            .note.gnu.gold-version
295     Type:            SHT_NOTE
296     AddressAlign:    0x0000000000000004
297     Content:         040000000900000004000000474E5500676F6C6420312E3131000000
298   - Name:            .ARM.attributes
299     Type:            SHT_ARM_ATTRIBUTES
300     AddressAlign:    0x0000000000000001
301     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