1 //===- XCOFFObjectFileTest.cpp - Tests for XCOFFObjectFile ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Object/ELFObjectFile.h"
10 #include "llvm/Object/XCOFFObjectFile.h"
11 #include "llvm/Testing/Support/Error.h"
12 #include "gtest/gtest.h"
13
14 using namespace llvm;
15 using namespace llvm::object;
16 using namespace llvm::XCOFF;
17
TEST(XCOFFObjectFileTest,XCOFFObjectType)18 TEST(XCOFFObjectFileTest, XCOFFObjectType) {
19 // Create an arbitrary object of a non-XCOFF type and test that
20 // dyn_cast<XCOFFObjectFile> returns null for it.
21 char Buf[sizeof(typename ELF64LE::Ehdr)] = {};
22 memcpy(Buf, "\177ELF", 4);
23
24 auto *EHdr = reinterpret_cast<typename ELF64LE::Ehdr *>(Buf);
25 EHdr->e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;
26 EHdr->e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;
27
28 MemoryBufferRef Source(StringRef(Buf, sizeof(Buf)), "non-XCOFF");
29 Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
30 ObjectFile::createObjectFile(Source);
31 ASSERT_THAT_EXPECTED(ObjOrErr, Succeeded());
32
33 EXPECT_TRUE(dyn_cast<XCOFFObjectFile>((*ObjOrErr).get()) == nullptr);
34 }
35
TEST(XCOFFObjectFileTest,doesXCOFFTracebackTableBegin)36 TEST(XCOFFObjectFileTest, doesXCOFFTracebackTableBegin) {
37 EXPECT_TRUE(doesXCOFFTracebackTableBegin({0, 0, 0, 0}));
38 EXPECT_TRUE(doesXCOFFTracebackTableBegin({0, 0, 0, 0, 1}));
39 EXPECT_FALSE(doesXCOFFTracebackTableBegin({0, 0, 0, 1}));
40 EXPECT_FALSE(doesXCOFFTracebackTableBegin({0, 0, 0}));
41 }
42
TEST(XCOFFObjectFileTest,XCOFFTracebackTableAPIGeneral)43 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIGeneral) {
44 uint8_t V[] = {0x00, 0x00, 0x22, 0x40, 0x80, 0x00, 0x01, 0x05, 0x58, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x61, 0x64,
46 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
47 uint64_t Size = sizeof(V);
48 Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
49 ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
50 XCOFFTracebackTable TT = *TTOrErr;
51
52 EXPECT_EQ(TT.getVersion(), 0);
53
54 EXPECT_EQ(TT.getLanguageID(), 0);
55
56 EXPECT_FALSE(TT.isGlobalLinkage());
57 EXPECT_FALSE(TT.isOutOfLineEpilogOrPrologue());
58 EXPECT_TRUE(TT.hasTraceBackTableOffset());
59 EXPECT_FALSE(TT.isInternalProcedure());
60 EXPECT_FALSE(TT.hasControlledStorage());
61 EXPECT_FALSE(TT.isTOCless());
62 EXPECT_TRUE(TT.isFloatingPointPresent());
63 EXPECT_FALSE(TT.isFloatingPointOperationLogOrAbortEnabled());
64
65 EXPECT_FALSE(TT.isInterruptHandler());
66 EXPECT_TRUE(TT.isFuncNamePresent());
67 EXPECT_FALSE(TT.isAllocaUsed());
68 EXPECT_EQ(TT.getOnConditionDirective(), 0);
69 EXPECT_FALSE(TT.isCRSaved());
70 EXPECT_FALSE(TT.isLRSaved());
71
72 EXPECT_TRUE(TT.isBackChainStored());
73 EXPECT_FALSE(TT.isFixup());
74 EXPECT_EQ(TT.getNumOfFPRsSaved(), 0);
75
76 EXPECT_FALSE(TT.hasExtensionTable());
77 EXPECT_FALSE(TT.hasVectorInfo());
78 EXPECT_EQ(TT.getNumOfGPRsSaved(), 0);
79
80 EXPECT_EQ(TT.getNumberOfFixedParms(), 1);
81
82 EXPECT_EQ(TT.getNumberOfFPParms(), 2);
83 EXPECT_TRUE(TT.hasParmsOnStack());
84
85 ASSERT_TRUE(TT.getParmsType());
86 EXPECT_EQ(TT.getParmsType().getValue(), "i, f, d");
87
88 ASSERT_TRUE(TT.getTraceBackTableOffset());
89 EXPECT_EQ(TT.getTraceBackTableOffset().getValue(), 64u);
90
91 EXPECT_FALSE(TT.getHandlerMask());
92
93 ASSERT_TRUE(TT.getFunctionName());
94 EXPECT_EQ(TT.getFunctionName().getValue(), "add_all");
95 EXPECT_EQ(TT.getFunctionName().getValue().size(), 7u);
96
97 EXPECT_FALSE(TT.getAllocaRegister());
98 EXPECT_EQ(Size, 25u);
99 }
100
TEST(XCOFFObjectFileTest,XCOFFTracebackTableAPIParmsType)101 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIParmsType) {
102 uint8_t V[] = {0x01, 0x02, 0xA2, 0x40, 0x80, 0x00, 0x02, 0x07, 0x2B, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x61, 0x64,
104 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
105 uint64_t Size = sizeof(V);
106 Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
107
108 ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
109 XCOFFTracebackTable TT = *TTOrErr;
110 EXPECT_EQ(TT.getVersion(), 1);
111 EXPECT_EQ(TT.getLanguageID(), 2);
112
113 EXPECT_TRUE(TT.isGlobalLinkage());
114 EXPECT_EQ(TT.getNumberOfFixedParms(), 2);
115
116 EXPECT_EQ(TT.getNumberOfFPParms(), 3);
117
118 ASSERT_TRUE(TT.getParmsType());
119 EXPECT_EQ(TT.getParmsType().getValue(), "i, i, f, f, d");
120
121 V[8] = 0xAC;
122 Size = sizeof(V);
123 Expected<XCOFFTracebackTable> TTOrErr1 = XCOFFTracebackTable::create(V, Size);
124 ASSERT_THAT_EXPECTED(TTOrErr1, Succeeded());
125 XCOFFTracebackTable TT1 = *TTOrErr1;
126 ASSERT_TRUE(TT1.getParmsType());
127 EXPECT_EQ(TT1.getParmsType().getValue(), "f, f, d, i, i");
128
129 V[8] = 0xD4;
130 Size = sizeof(V);
131 Expected<XCOFFTracebackTable> TTOrErr2 = XCOFFTracebackTable::create(V, Size);
132 ASSERT_THAT_EXPECTED(TTOrErr2, Succeeded());
133 XCOFFTracebackTable TT2 = *TTOrErr2;
134 ASSERT_TRUE(TT2.getParmsType());
135 EXPECT_EQ(TT2.getParmsType().getValue(), "d, i, f, f, i");
136
137 V[6] = 0x01;
138 Size = sizeof(V);
139 Expected<XCOFFTracebackTable> TTOrErr3 = XCOFFTracebackTable::create(V, Size);
140 ASSERT_THAT_EXPECTED(TTOrErr3, Succeeded());
141 XCOFFTracebackTable TT3 = *TTOrErr3;
142 ASSERT_TRUE(TT3.getParmsType());
143 EXPECT_EQ(TT3.getParmsType().getValue(), "d, i, f, f");
144 }
145
146 const uint8_t TBTableData[] = {
147 0x00, 0x00, 0x2A, 0x60, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc4, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
149 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
150 0x6c, 0x1f, 0x02, 0x05, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
151
TEST(XCOFFObjectFileTest,XCOFFTracebackTableAPIControlledStorageInfoDisp)152 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
153 uint64_t Size = sizeof(TBTableData);
154 Expected<XCOFFTracebackTable> TTOrErr =
155 XCOFFTracebackTable::create(TBTableData, Size);
156 ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
157 XCOFFTracebackTable TT = *TTOrErr;
158 EXPECT_TRUE(TT.hasControlledStorage());
159 ASSERT_TRUE(TT.getNumOfCtlAnchors());
160 EXPECT_EQ(TT.getNumOfCtlAnchors().getValue(), 2u);
161
162 ASSERT_TRUE(TT.getControlledStorageInfoDisp());
163
164 SmallVector<uint32_t, 8> Disp = TT.getControlledStorageInfoDisp().getValue();
165
166 ASSERT_EQ(Disp.size(), 2UL);
167 EXPECT_EQ(Disp[0], 0x05050000u);
168 EXPECT_EQ(Disp[1], 0x06060000u);
169 EXPECT_EQ(Size, 45u);
170 }
171
TEST(XCOFFObjectFileTest,XCOFFTracebackTableAPIAllocaRegister)172 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIAllocaRegister) {
173 uint64_t Size = sizeof(TBTableData);
174 Expected<XCOFFTracebackTable> TTOrErr =
175 XCOFFTracebackTable::create(TBTableData, Size);
176 ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
177 XCOFFTracebackTable TT = *TTOrErr;
178 ASSERT_TRUE(TT.getAllocaRegister());
179 EXPECT_EQ(TT.getAllocaRegister().getValue(), 31u);
180 }
181
TEST(XCOFFObjectFileTest,XCOFFTracebackTableAPIHasVectorInfo)182 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
183
184 uint64_t Size = sizeof(TBTableData);
185 Expected<XCOFFTracebackTable> TTOrErr =
186 XCOFFTracebackTable::create(TBTableData, Size);
187 ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
188 XCOFFTracebackTable TT = *TTOrErr;
189
190 EXPECT_EQ(TT.getNumberOfFixedParms(), 3);
191 EXPECT_EQ(TT.getNumberOfFPParms(), 2);
192 EXPECT_TRUE(TT.hasVectorInfo());
193 EXPECT_TRUE(TT.hasExtensionTable());
194
195 ASSERT_TRUE(TT.getParmsType());
196 EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i, v");
197
198 ASSERT_TRUE(TT.getVectorExt());
199 TBVectorExt VecExt = TT.getVectorExt().getValue();
200
201 EXPECT_EQ(VecExt.getNumberOfVRSaved(), 0);
202 EXPECT_TRUE(VecExt.isVRSavedOnStack());
203 EXPECT_FALSE(VecExt.hasVarArgs());
204
205 EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u);
206 EXPECT_TRUE(VecExt.hasVMXInstruction());
207
208 EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vf, vf");
209
210 ASSERT_TRUE(TT.getExtensionTable());
211 EXPECT_EQ(TT.getExtensionTable().getValue(),
212 ExtendedTBTableFlag::TB_SSP_CANARY);
213
214 EXPECT_EQ(Size, 45u);
215 }
216
TEST(XCOFFObjectFileTest,XCOFFTracebackTableAPIHasVectorInfo1)217 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
218 const uint8_t TBTableData[] = {
219 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
221 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
222 0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
223 uint64_t Size = sizeof(TBTableData);
224 Expected<XCOFFTracebackTable> TTOrErr =
225 XCOFFTracebackTable::create(TBTableData, Size);
226 ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
227 XCOFFTracebackTable TT = *TTOrErr;
228
229 ASSERT_TRUE(TT.getParmsType());
230 EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i");
231
232 ASSERT_TRUE(TT.getVectorExt());
233 TBVectorExt VecExt = TT.getVectorExt().getValue();
234
235 EXPECT_EQ(VecExt.getNumberOfVRSaved(), 4);
236 EXPECT_FALSE(VecExt.isVRSavedOnStack());
237 EXPECT_TRUE(VecExt.hasVarArgs());
238
239 EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u);
240 EXPECT_TRUE(VecExt.hasVMXInstruction());
241
242 EXPECT_EQ(VecExt.getVectorParmsInfoString(), "vi, vs, vc");
243
244 ASSERT_TRUE(TT.getExtensionTable());
245 EXPECT_EQ(TT.getExtensionTable().getValue(),
246 ExtendedTBTableFlag::TB_SSP_CANARY);
247
248 EXPECT_EQ(Size, 44u);
249 }
250
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtMandatory)251 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) {
252 uint64_t Size = 6;
253 Expected<XCOFFTracebackTable> TTOrErr =
254 XCOFFTracebackTable::create(TBTableData, Size);
255 EXPECT_THAT_ERROR(
256 TTOrErr.takeError(),
257 FailedWithMessage(
258 "unexpected end of data at offset 0x6 while reading [0x0, 0x8)"));
259 EXPECT_EQ(Size, 0u);
260 }
261
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtParmsType)262 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtParmsType) {
263 uint64_t Size = 9;
264 Expected<XCOFFTracebackTable> TTOrErr =
265 XCOFFTracebackTable::create(TBTableData, Size);
266 EXPECT_THAT_ERROR(
267 TTOrErr.takeError(),
268 FailedWithMessage(
269 "unexpected end of data at offset 0x9 while reading [0x8, 0xc)"));
270 EXPECT_EQ(Size, 8u);
271 }
272
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtTBOffset)273 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtTBOffset) {
274 uint64_t Size = 14;
275 Expected<XCOFFTracebackTable> TTOrErr =
276 XCOFFTracebackTable::create(TBTableData, Size);
277 EXPECT_THAT_ERROR(
278 TTOrErr.takeError(),
279 FailedWithMessage(
280 "unexpected end of data at offset 0xe while reading [0xc, 0x10)"));
281 EXPECT_EQ(Size, 12u);
282 }
283
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtHandlerMask)284 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtHandlerMask) {
285 uint8_t V[] = {0x00, 0x00, 0x22, 0xC0, 0x80, 0x00, 0x01, 0x05, 0x58,
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07};
287 uint64_t Size = sizeof(V);
288 Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
289 EXPECT_THAT_ERROR(
290 TTOrErr.takeError(),
291 FailedWithMessage(
292 "unexpected end of data at offset 0x12 while reading [0x10, 0x14)"));
293 EXPECT_EQ(Size, 16u);
294 }
295
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtNumOfCtlAnchors)296 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNumOfCtlAnchors) {
297 uint64_t Size = 19;
298 Expected<XCOFFTracebackTable> TTOrErr =
299 XCOFFTracebackTable::create(TBTableData, Size);
300 EXPECT_THAT_ERROR(
301 TTOrErr.takeError(),
302 FailedWithMessage(
303 "unexpected end of data at offset 0x13 while reading [0x10, 0x14)"));
304 EXPECT_EQ(Size, 16u);
305 }
306
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtControlledStorageInfoDisp)307 TEST(XCOFFObjectFileTest,
308 XCOFFTracebackTableTruncatedAtControlledStorageInfoDisp) {
309 uint64_t Size = 21;
310 Expected<XCOFFTracebackTable> TTOrErr =
311 XCOFFTracebackTable::create(TBTableData, Size);
312 EXPECT_THAT_ERROR(
313 TTOrErr.takeError(),
314 FailedWithMessage(
315 "unexpected end of data at offset 0x15 while reading [0x14, 0x18)"));
316 EXPECT_EQ(Size, 20u);
317 }
318
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtNameLen)319 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNameLen) {
320 uint64_t Size = 29;
321 Expected<XCOFFTracebackTable> TTOrErr =
322 XCOFFTracebackTable::create(TBTableData, Size);
323 EXPECT_THAT_ERROR(
324 TTOrErr.takeError(),
325 FailedWithMessage(
326 "unexpected end of data at offset 0x1d while reading [0x1c, 0x1e)"));
327 EXPECT_EQ(Size, 28u);
328 }
329
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtFunctionName)330 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtFunctionName) {
331 uint64_t Size = 36;
332 Expected<XCOFFTracebackTable> TTOrErr =
333 XCOFFTracebackTable::create(TBTableData, Size);
334 EXPECT_THAT_ERROR(
335 TTOrErr.takeError(),
336 FailedWithMessage(
337 "unexpected end of data at offset 0x24 while reading [0x1e, 0x25)"));
338 EXPECT_EQ(Size, 30u);
339 }
340
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtAllocaUsed)341 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtAllocaUsed) {
342 uint64_t Size = 37;
343 Expected<XCOFFTracebackTable> TTOrErr =
344 XCOFFTracebackTable::create(TBTableData, Size);
345 EXPECT_THAT_ERROR(
346 TTOrErr.takeError(),
347 FailedWithMessage(
348 "unexpected end of data at offset 0x25 while reading [0x25, 0x26)"));
349 EXPECT_EQ(Size, 37u);
350 }
351
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtVectorInfoData)352 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoData) {
353 uint64_t Size = 39;
354 Expected<XCOFFTracebackTable> TTOrErr =
355 XCOFFTracebackTable::create(TBTableData, Size);
356
357 EXPECT_THAT_ERROR(
358 TTOrErr.takeError(),
359 FailedWithMessage(
360 "unexpected end of data at offset 0x27 while reading [0x26, 0x2c)"));
361 EXPECT_EQ(Size, 38u);
362 }
363
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtVectorInfoParmsInfo)364 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoParmsInfo) {
365 uint64_t Size = 43;
366 Expected<XCOFFTracebackTable> TTOrErr =
367 XCOFFTracebackTable::create(TBTableData, Size);
368
369 EXPECT_THAT_ERROR(
370 TTOrErr.takeError(),
371 FailedWithMessage(
372 "unexpected end of data at offset 0x2b while reading [0x26, 0x2c)"));
373 EXPECT_EQ(Size, 38u);
374 }
375
TEST(XCOFFObjectFileTest,XCOFFTracebackTableTruncatedAtExtLongTBTable)376 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtExtLongTBTable) {
377 uint64_t Size = 44;
378 Expected<XCOFFTracebackTable> TTOrErr =
379 XCOFFTracebackTable::create(TBTableData, Size);
380
381 EXPECT_THAT_ERROR(
382 TTOrErr.takeError(),
383 FailedWithMessage(
384 "unexpected end of data at offset 0x2c while reading [0x2c, 0x2d)"));
385 EXPECT_EQ(Size, 44u);
386 }
387