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