xref: /llvm-project/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp (revision 5dca0596a959217a1c18858a62ed35245a4c42b4)
1 //===-- TestObjectFileELF.cpp -----------------------------------*- C++ -*-===//
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   ModuleSpec spec{FileSpec(ExpectedFile->name())};
95   spec.GetSymbolFileSpec().SetFile(ExpectedFile->name(),
96                                    FileSpec::Style::native);
97   auto module_sp = std::make_shared<Module>(spec);
98   SectionList *list = module_sp->GetSectionList();
99   ASSERT_NE(nullptr, list);
100 
101   auto bss_sp = list->FindSectionByName(ConstString(".bss"));
102   ASSERT_NE(nullptr, bss_sp);
103   auto data_sp = list->FindSectionByName(ConstString(".data"));
104   ASSERT_NE(nullptr, data_sp);
105   auto text_sp = list->FindSectionByName(ConstString(".text"));
106   ASSERT_NE(nullptr, text_sp);
107 
108   const Symbol *X = module_sp->FindFirstSymbolWithNameAndType(ConstString("X"),
109                                                               eSymbolTypeAny);
110   ASSERT_NE(nullptr, X);
111   EXPECT_EQ(bss_sp, X->GetAddress().GetSection());
112 
113   const Symbol *Y = module_sp->FindFirstSymbolWithNameAndType(ConstString("Y"),
114                                                               eSymbolTypeAny);
115   ASSERT_NE(nullptr, Y);
116   EXPECT_EQ(data_sp, Y->GetAddress().GetSection());
117 
118   const Symbol *start = module_sp->FindFirstSymbolWithNameAndType(
119       ConstString("_start"), eSymbolTypeAny);
120   ASSERT_NE(nullptr, start);
121   EXPECT_EQ(text_sp, start->GetAddress().GetSection());
122 }
123 
124 // Test that GetModuleSpecifications works on an "atypical" object file which
125 // has section headers right after the ELF header (instead of the more common
126 // layout where the section headers are at the very end of the object file).
127 //
128 // Test file generated with yaml2obj (@svn rev 324254) from the following input:
129 /*
130 --- !ELF
131 FileHeader:
132   Class:           ELFCLASS64
133   Data:            ELFDATA2LSB
134   Type:            ET_EXEC
135   Machine:         EM_X86_64
136   Entry:           0x00000000004003D0
137 Sections:
138   - Name:            .note.gnu.build-id
139     Type:            SHT_NOTE
140     Flags:           [ SHF_ALLOC ]
141     Address:         0x0000000000400274
142     AddressAlign:    0x0000000000000004
143     Content:         040000001400000003000000474E55001B8A73AC238390E32A7FF4AC8EBE4D6A41ECF5C9
144   - Name:            .text
145     Type:            SHT_PROGBITS
146     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
147     Address:         0x00000000004003D0
148     AddressAlign:    0x0000000000000010
149     Content:         DEADBEEFBAADF00D
150 ...
151 */
152 TEST_F(ObjectFileELFTest, GetModuleSpecifications_EarlySectionHeaders) {
153   std::string SO = GetInputFilePath("early-section-headers.so");
154   ModuleSpecList Specs;
155   ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 0, 0, Specs));
156   ModuleSpec Spec;
157   ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ;
158   UUID Uuid;
159   Uuid.SetFromStringRef("1b8a73ac238390e32a7ff4ac8ebe4d6a41ecf5c9", 20);
160   EXPECT_EQ(Spec.GetUUID(), Uuid);
161 }
162 
163 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmThumbAddressClass) {
164   /*
165   // nosym-entrypoint-arm-thumb.s
166   .thumb_func
167   _start:
168       mov r0, #42
169       mov r7, #1
170       svc #0
171   // arm-linux-androideabi-as nosym-entrypoint-arm-thumb.s
172   //   -o nosym-entrypoint-arm-thumb.o
173   // arm-linux-androideabi-ld nosym-entrypoint-arm-thumb.o
174   //   -o nosym-entrypoint-arm-thumb -e 0x8075 -s
175   */
176   auto ExpectedFile = TestFile::fromYaml(R"(
177 --- !ELF
178 FileHeader:
179   Class:           ELFCLASS32
180   Data:            ELFDATA2LSB
181   Type:            ET_EXEC
182   Machine:         EM_ARM
183   Flags:           [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
184   Entry:           0x0000000000008075
185 Sections:
186   - Name:            .text
187     Type:            SHT_PROGBITS
188     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
189     Address:         0x0000000000008074
190     AddressAlign:    0x0000000000000002
191     Content:         2A20012700DF
192   - Name:            .data
193     Type:            SHT_PROGBITS
194     Flags:           [ SHF_WRITE, SHF_ALLOC ]
195     Address:         0x0000000000009000
196     AddressAlign:    0x0000000000000001
197     Content:         ''
198   - Name:            .bss
199     Type:            SHT_NOBITS
200     Flags:           [ SHF_WRITE, SHF_ALLOC ]
201     Address:         0x0000000000009000
202     AddressAlign:    0x0000000000000001
203   - Name:            .note.gnu.gold-version
204     Type:            SHT_NOTE
205     AddressAlign:    0x0000000000000004
206     Content:         040000000900000004000000474E5500676F6C6420312E3131000000
207   - Name:            .ARM.attributes
208     Type:            SHT_ARM_ATTRIBUTES
209     AddressAlign:    0x0000000000000001
210     Content:         '4113000000616561626900010900000006020901'
211 ...
212 )");
213   ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
214 
215   ModuleSpec spec{FileSpec(ExpectedFile->name())};
216   spec.GetSymbolFileSpec().SetFile(ExpectedFile->name(),
217                                    FileSpec::Style::native);
218   auto module_sp = std::make_shared<Module>(spec);
219 
220   auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress();
221   ASSERT_TRUE(entry_point_addr.GetOffset() & 1);
222   // Decrease the offsite by 1 to make it into a breakable address since this
223   // is Thumb.
224   entry_point_addr.SetOffset(entry_point_addr.GetOffset() - 1);
225   ASSERT_EQ(entry_point_addr.GetAddressClass(),
226             AddressClass::eCodeAlternateISA);
227 }
228 
229 TEST_F(ObjectFileELFTest, GetSymtab_NoSymEntryPointArmAddressClass) {
230   /*
231   // nosym-entrypoint-arm.s
232   _start:
233       movs r0, #42
234       movs r7, #1
235       svc #0
236   // arm-linux-androideabi-as nosym-entrypoint-arm.s
237   //   -o nosym-entrypoint-arm.o
238   // arm-linux-androideabi-ld nosym-entrypoint-arm.o
239   //   -o nosym-entrypoint-arm -e 0x8074 -s
240   */
241   auto ExpectedFile = TestFile::fromYaml(R"(
242 --- !ELF
243 FileHeader:
244   Class:           ELFCLASS32
245   Data:            ELFDATA2LSB
246   Type:            ET_EXEC
247   Machine:         EM_ARM
248   Flags:           [ EF_ARM_SOFT_FLOAT, EF_ARM_EABI_VER5 ]
249   Entry:           0x0000000000008074
250 Sections:
251   - Name:            .text
252     Type:            SHT_PROGBITS
253     Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
254     Address:         0x0000000000008074
255     AddressAlign:    0x0000000000000004
256     Content:         2A00A0E30170A0E3000000EF
257   - Name:            .data
258     Type:            SHT_PROGBITS
259     Flags:           [ SHF_WRITE, SHF_ALLOC ]
260     Address:         0x0000000000009000
261     AddressAlign:    0x0000000000000001
262     Content:         ''
263   - Name:            .bss
264     Type:            SHT_NOBITS
265     Flags:           [ SHF_WRITE, SHF_ALLOC ]
266     Address:         0x0000000000009000
267     AddressAlign:    0x0000000000000001
268   - Name:            .note.gnu.gold-version
269     Type:            SHT_NOTE
270     AddressAlign:    0x0000000000000004
271     Content:         040000000900000004000000474E5500676F6C6420312E3131000000
272   - Name:            .ARM.attributes
273     Type:            SHT_ARM_ATTRIBUTES
274     AddressAlign:    0x0000000000000001
275     Content:         '4113000000616561626900010900000006010801'
276 ...
277 )");
278   ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
279 
280   ModuleSpec spec{FileSpec(ExpectedFile->name())};
281   spec.GetSymbolFileSpec().SetFile(ExpectedFile->name(),
282                                    FileSpec::Style::native);
283   auto module_sp = std::make_shared<Module>(spec);
284 
285   auto entry_point_addr = module_sp->GetObjectFile()->GetEntryPointAddress();
286   ASSERT_EQ(entry_point_addr.GetAddressClass(), AddressClass::eCode);
287 }