xref: /llvm-project/llvm/unittests/Object/XCOFFObjectFileTest.cpp (revision 92c527e5a2b49fb1213ceda97738d4caf414666a)
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 
17 TEST(XCOFFObjectFileTest, XCOFFObjectType) {
18   // Create an arbitrary object of a non-XCOFF type and test that
19   // dyn_cast<XCOFFObjectFile> returns null for it.
20   char Buf[sizeof(typename ELF64LE::Ehdr)] = {};
21   memcpy(Buf, "\177ELF", 4);
22 
23   auto *EHdr = reinterpret_cast<typename ELF64LE::Ehdr *>(Buf);
24   EHdr->e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;
25   EHdr->e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;
26 
27   MemoryBufferRef Source(StringRef(Buf, sizeof(Buf)), "non-XCOFF");
28   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
29       ObjectFile::createObjectFile(Source);
30   ASSERT_THAT_EXPECTED(ObjOrErr, Succeeded());
31 
32   EXPECT_TRUE(dyn_cast<XCOFFObjectFile>((*ObjOrErr).get()) == nullptr);
33 }
34 
35 TEST(XCOFFObjectFileTest, doesXCOFFTracebackTableBegin) {
36   EXPECT_TRUE(doesXCOFFTracebackTableBegin({0, 0, 0, 0}));
37   EXPECT_TRUE(doesXCOFFTracebackTableBegin({0, 0, 0, 0, 1}));
38   EXPECT_FALSE(doesXCOFFTracebackTableBegin({0, 0, 0, 1}));
39   EXPECT_FALSE(doesXCOFFTracebackTableBegin({0, 0, 0}));
40 }
41 
42 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIGeneral) {
43   uint8_t V[] = {0x00, 0x00, 0x22, 0x40, 0x80, 0x00, 0x01, 0x05, 0x58, 0x00,
44                  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x61, 0x64,
45                  0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
46   uint64_t Size = sizeof(V);
47   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
48   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
49   XCOFFTracebackTable TT = *TTOrErr;
50 
51   EXPECT_EQ(TT.getVersion(), 0);
52 
53   EXPECT_EQ(TT.getLanguageID(), 0);
54 
55   EXPECT_FALSE(TT.isGlobalLinkage());
56   EXPECT_FALSE(TT.isOutOfLineEpilogOrPrologue());
57   EXPECT_TRUE(TT.hasTraceBackTableOffset());
58   EXPECT_FALSE(TT.isInternalProcedure());
59   EXPECT_FALSE(TT.hasControlledStorage());
60   EXPECT_FALSE(TT.isTOCless());
61   EXPECT_TRUE(TT.isFloatingPointPresent());
62   EXPECT_FALSE(TT.isFloatingPointOperationLogOrAbortEnabled());
63 
64   EXPECT_FALSE(TT.isInterruptHandler());
65   EXPECT_TRUE(TT.isFuncNamePresent());
66   EXPECT_FALSE(TT.isAllocaUsed());
67   EXPECT_EQ(TT.getOnConditionDirective(), 0);
68   EXPECT_FALSE(TT.isCRSaved());
69   EXPECT_FALSE(TT.isLRSaved());
70 
71   EXPECT_TRUE(TT.isBackChainStored());
72   EXPECT_FALSE(TT.isFixup());
73   EXPECT_EQ(TT.getNumOfFPRsSaved(), 0);
74 
75   EXPECT_FALSE(TT.hasExtensionTable());
76   EXPECT_FALSE(TT.hasVectorInfo());
77   EXPECT_EQ(TT.getNumofGPRsSaved(), 0);
78 
79   EXPECT_EQ(TT.getNumberOfFixedParms(), 1);
80 
81   EXPECT_EQ(TT.getNumberOfFPParms(), 2);
82   EXPECT_TRUE(TT.hasParmsOnStack());
83 
84   ASSERT_TRUE(TT.getParmsType());
85   EXPECT_EQ(TT.getParmsType().getValue(), "i, f, d");
86 
87   ASSERT_TRUE(TT.getTraceBackTableOffset());
88   EXPECT_EQ(TT.getTraceBackTableOffset().getValue(), 64u);
89 
90   EXPECT_FALSE(TT.getHandlerMask());
91 
92   ASSERT_TRUE(TT.getFunctionName());
93   EXPECT_EQ(TT.getFunctionName().getValue(), "add_all");
94   EXPECT_EQ(TT.getFunctionName().getValue().size(), 7u);
95 
96   EXPECT_FALSE(TT.getAllocaRegister());
97   EXPECT_EQ(Size, 25u);
98 }
99 
100 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIParmsType) {
101   uint8_t V[] = {0x01, 0x02, 0xA2, 0x40, 0x80, 0x00, 0x02, 0x07, 0x2B, 0x00,
102                  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x61, 0x64,
103                  0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
104   uint64_t Size = sizeof(V);
105   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
106 
107   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
108   XCOFFTracebackTable TT = *TTOrErr;
109   EXPECT_EQ(TT.getVersion(), 1);
110   EXPECT_EQ(TT.getLanguageID(), 2);
111 
112   EXPECT_TRUE(TT.isGlobalLinkage());
113   EXPECT_EQ(TT.getNumberOfFixedParms(), 2);
114 
115   EXPECT_EQ(TT.getNumberOfFPParms(), 3);
116 
117   ASSERT_TRUE(TT.getParmsType());
118   EXPECT_EQ(TT.getParmsType().getValue(), "i, i, f, f, d");
119 
120   V[8] = 0xAC;
121   Size = sizeof(V);
122   Expected<XCOFFTracebackTable> TTOrErr1 = XCOFFTracebackTable::create(V, Size);
123   ASSERT_THAT_EXPECTED(TTOrErr1, Succeeded());
124   XCOFFTracebackTable TT1 = *TTOrErr1;
125   ASSERT_TRUE(TT1.getParmsType());
126   EXPECT_EQ(TT1.getParmsType().getValue(), "f, f, d, i, i");
127 
128   V[8] = 0xD4;
129   Size = sizeof(V);
130   Expected<XCOFFTracebackTable> TTOrErr2 = XCOFFTracebackTable::create(V, Size);
131   ASSERT_THAT_EXPECTED(TTOrErr2, Succeeded());
132   XCOFFTracebackTable TT2 = *TTOrErr2;
133   ASSERT_TRUE(TT2.getParmsType());
134   EXPECT_EQ(TT2.getParmsType().getValue(), "d, i, f, f, i");
135 
136   V[6] = 0x01;
137   Size = sizeof(V);
138   Expected<XCOFFTracebackTable> TTOrErr3 = XCOFFTracebackTable::create(V, Size);
139   ASSERT_THAT_EXPECTED(TTOrErr3, Succeeded());
140   XCOFFTracebackTable TT3 = *TTOrErr3;
141   ASSERT_TRUE(TT3.getParmsType());
142   EXPECT_EQ(TT3.getParmsType().getValue(), "d, i, f, f");
143 }
144 
145 const uint8_t TBTableData[] = {0x00, 0x00, 0x2A, 0x40, 0x80, 0x40, 0x01, 0x05,
146                                0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
147                                0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
148                                0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64,
149                                0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
150 
151 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
152   uint64_t Size = 40;
153   Expected<XCOFFTracebackTable> TTOrErr =
154       XCOFFTracebackTable::create(TBTableData, Size);
155   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
156   XCOFFTracebackTable TT = *TTOrErr;
157   EXPECT_TRUE(TT.hasControlledStorage());
158   ASSERT_TRUE(TT.getNumOfCtlAnchors());
159   EXPECT_EQ(TT.getNumOfCtlAnchors().getValue(), 2u);
160 
161   ASSERT_TRUE(TT.getControlledStorageInfoDisp());
162 
163   SmallVector<uint32_t, 8> Disp = TT.getControlledStorageInfoDisp().getValue();
164 
165   ASSERT_EQ(Disp.size(), 2UL);
166   EXPECT_EQ(Disp[0], 0x05050000u);
167   EXPECT_EQ(Disp[1], 0x06060000u);
168 }
169 
170 TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
171   uint64_t Size = 40;
172   Expected<XCOFFTracebackTable> TTOrErr =
173       XCOFFTracebackTable::create(TBTableData, Size);
174   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
175   XCOFFTracebackTable TT = *TTOrErr;
176 
177   EXPECT_TRUE(TT.hasVectorInfo());
178   EXPECT_FALSE(TT.getParmsType());
179 }
180 
181 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) {
182   uint64_t Size = 6;
183   Expected<XCOFFTracebackTable> TTOrErr =
184       XCOFFTracebackTable::create(TBTableData, Size);
185   EXPECT_THAT_ERROR(
186       TTOrErr.takeError(),
187       FailedWithMessage(
188           "unexpected end of data at offset 0x6 while reading [0x0, 0x8)"));
189   EXPECT_EQ(Size, 0UL);
190 }
191 
192 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtParmsType) {
193   uint64_t Size = 9;
194   Expected<XCOFFTracebackTable> TTOrErr =
195       XCOFFTracebackTable::create(TBTableData, Size);
196   EXPECT_THAT_ERROR(
197       TTOrErr.takeError(),
198       FailedWithMessage(
199           "unexpected end of data at offset 0x9 while reading [0x8, 0xc)"));
200   EXPECT_EQ(Size, 8u);
201 }
202 
203 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtTBOffset) {
204   uint64_t Size = 14;
205   Expected<XCOFFTracebackTable> TTOrErr =
206       XCOFFTracebackTable::create(TBTableData, Size);
207   EXPECT_THAT_ERROR(
208       TTOrErr.takeError(),
209       FailedWithMessage(
210           "unexpected end of data at offset 0xe while reading [0xc, 0x10)"));
211   EXPECT_EQ(Size, 12u);
212 }
213 
214 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtHandlerMask) {
215   uint8_t V[] = {0x00, 0x00, 0x22, 0xC0, 0x80, 0x00, 0x01, 0x05, 0x58,
216                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07};
217   uint64_t Size = sizeof(V);
218   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
219   EXPECT_THAT_ERROR(
220       TTOrErr.takeError(),
221       FailedWithMessage(
222           "unexpected end of data at offset 0x12 while reading [0x10, 0x14)"));
223   EXPECT_EQ(Size, 16u);
224 }
225 
226 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNumOfCtlAnchors) {
227   uint64_t Size = 19;
228   Expected<XCOFFTracebackTable> TTOrErr =
229       XCOFFTracebackTable::create(TBTableData, Size);
230   EXPECT_THAT_ERROR(
231       TTOrErr.takeError(),
232       FailedWithMessage(
233           "unexpected end of data at offset 0x13 while reading [0x10, 0x14)"));
234   EXPECT_EQ(Size, 16u);
235 }
236 
237 TEST(XCOFFObjectFileTest,
238      XCOFFTracebackTableTruncatedAtControlledStorageInfoDisp) {
239   uint64_t Size = 21;
240   Expected<XCOFFTracebackTable> TTOrErr =
241       XCOFFTracebackTable::create(TBTableData, Size);
242   EXPECT_THAT_ERROR(
243       TTOrErr.takeError(),
244       FailedWithMessage(
245           "unexpected end of data at offset 0x15 while reading [0x14, 0x18)"));
246   EXPECT_EQ(Size, 20u);
247 }
248 
249 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNameLen) {
250   uint64_t Size = 29;
251   Expected<XCOFFTracebackTable> TTOrErr =
252       XCOFFTracebackTable::create(TBTableData, Size);
253   EXPECT_THAT_ERROR(
254       TTOrErr.takeError(),
255       FailedWithMessage(
256           "unexpected end of data at offset 0x1d while reading [0x1c, 0x1e)"));
257   EXPECT_EQ(Size, 28u);
258 }
259 
260 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtFunctionName) {
261   uint64_t Size = 36;
262   Expected<XCOFFTracebackTable> TTOrErr =
263       XCOFFTracebackTable::create(TBTableData, Size);
264   EXPECT_THAT_ERROR(
265       TTOrErr.takeError(),
266       FailedWithMessage(
267           "unexpected end of data at offset 0x24 while reading [0x1e, 0x25)"));
268   EXPECT_EQ(Size, 30u);
269 }
270 
271 TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtAllocaUsed) {
272   uint8_t V[] = {0x00, 0x00, 0x2A, 0x60, 0x80, 0x00, 0x01, 0x05, 0x58, 0x00,
273                  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02,
274                  0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07,
275                  0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c};
276   uint64_t Size = sizeof(V);
277   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
278   EXPECT_THAT_ERROR(
279       TTOrErr.takeError(),
280       FailedWithMessage(
281           "unexpected end of data at offset 0x25 while reading [0x25, 0x26)"));
282   EXPECT_EQ(Size, 37u);
283 }
284