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 | |
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(dest: Buf, src: "\177ELF" , n: 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(Object: Source); |
31 | ASSERT_THAT_EXPECTED(ObjOrErr, Succeeded()); |
32 | |
33 | EXPECT_TRUE(dyn_cast<XCOFFObjectFile>((*ObjOrErr).get()) == nullptr); |
34 | } |
35 | |
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 | |
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(Ptr: 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(), "i, f, d" ); |
87 | |
88 | ASSERT_TRUE(TT.getTraceBackTableOffset()); |
89 | EXPECT_EQ(*TT.getTraceBackTableOffset(), 64u); |
90 | |
91 | EXPECT_FALSE(TT.getHandlerMask()); |
92 | |
93 | ASSERT_TRUE(TT.getFunctionName()); |
94 | EXPECT_EQ(*TT.getFunctionName(), "add_all" ); |
95 | EXPECT_EQ(TT.getFunctionName()->size(), 7u); |
96 | |
97 | EXPECT_FALSE(TT.getAllocaRegister()); |
98 | EXPECT_EQ(Size, 25u); |
99 | } |
100 | |
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(Ptr: 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(), "i, i, f, f, d" ); |
120 | |
121 | V[8] = 0xAC; |
122 | Size = sizeof(V); |
123 | Expected<XCOFFTracebackTable> TTOrErr1 = XCOFFTracebackTable::create(Ptr: V, Size); |
124 | ASSERT_THAT_EXPECTED(TTOrErr1, Succeeded()); |
125 | XCOFFTracebackTable TT1 = *TTOrErr1; |
126 | ASSERT_TRUE(TT1.getParmsType()); |
127 | EXPECT_EQ(*TT1.getParmsType(), "f, f, d, i, i" ); |
128 | |
129 | V[8] = 0xD4; |
130 | Size = sizeof(V); |
131 | Expected<XCOFFTracebackTable> TTOrErr2 = XCOFFTracebackTable::create(Ptr: V, Size); |
132 | ASSERT_THAT_EXPECTED(TTOrErr2, Succeeded()); |
133 | XCOFFTracebackTable TT2 = *TTOrErr2; |
134 | ASSERT_TRUE(TT2.getParmsType()); |
135 | EXPECT_EQ(*TT2.getParmsType(), "d, i, f, f, i" ); |
136 | |
137 | V[6] = 0x01; |
138 | Size = sizeof(V); |
139 | Expected<XCOFFTracebackTable> TTOrErr3 = XCOFFTracebackTable::create(Ptr: V, Size); |
140 | ASSERT_THAT_EXPECTED(TTOrErr3, Succeeded()); |
141 | XCOFFTracebackTable TT3 = *TTOrErr3; |
142 | ASSERT_TRUE(TT3.getParmsType()); |
143 | EXPECT_EQ(*TT3.getParmsType(), "d, i, f, f" ); |
144 | |
145 | V[6] = 0x04; |
146 | V[7] = 0x1E; |
147 | V[8] = 0xAC; |
148 | V[9] = 0xAA; |
149 | V[10] = 0xAA; |
150 | V[11] = 0xAA; |
151 | Size = sizeof(V); |
152 | Expected<XCOFFTracebackTable> TTOrErr4 = XCOFFTracebackTable::create(Ptr: V, Size); |
153 | ASSERT_THAT_EXPECTED(TTOrErr4, Succeeded()); |
154 | XCOFFTracebackTable TT4 = *TTOrErr4; |
155 | ASSERT_TRUE(TT4.getParmsType()); |
156 | EXPECT_EQ(*TT4.getParmsType(), |
157 | "f, f, d, i, i, f, f, f, f, f, f, f, f, f, f, f, f, ..." ); |
158 | } |
159 | |
160 | const uint8_t TBTableData[] = { |
161 | 0x00, 0x00, 0x2A, 0x60, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc4, |
162 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, |
163 | 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, |
164 | 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x1f, 0x02, 0x05, |
165 | 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; |
166 | |
167 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) { |
168 | uint64_t Size = sizeof(TBTableData); |
169 | Expected<XCOFFTracebackTable> TTOrErr = |
170 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
171 | ASSERT_THAT_EXPECTED(TTOrErr, Succeeded()); |
172 | XCOFFTracebackTable TT = *TTOrErr; |
173 | EXPECT_TRUE(TT.hasControlledStorage()); |
174 | ASSERT_TRUE(TT.getNumOfCtlAnchors()); |
175 | EXPECT_EQ(*TT.getNumOfCtlAnchors(), 2u); |
176 | |
177 | ASSERT_TRUE(TT.getControlledStorageInfoDisp()); |
178 | |
179 | SmallVector<uint32_t, 8> Disp = *TT.getControlledStorageInfoDisp(); |
180 | |
181 | ASSERT_EQ(Disp.size(), 2UL); |
182 | EXPECT_EQ(Disp[0], 0x05050000u); |
183 | EXPECT_EQ(Disp[1], 0x06060000u); |
184 | EXPECT_EQ(Size, 47u); |
185 | } |
186 | |
187 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIAllocaRegister) { |
188 | uint64_t Size = sizeof(TBTableData); |
189 | Expected<XCOFFTracebackTable> TTOrErr = |
190 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
191 | ASSERT_THAT_EXPECTED(TTOrErr, Succeeded()); |
192 | XCOFFTracebackTable TT = *TTOrErr; |
193 | ASSERT_TRUE(TT.getAllocaRegister()); |
194 | EXPECT_EQ(*TT.getAllocaRegister(), 31u); |
195 | } |
196 | |
197 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) { |
198 | |
199 | uint64_t Size = sizeof(TBTableData); |
200 | Expected<XCOFFTracebackTable> TTOrErr = |
201 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
202 | ASSERT_THAT_EXPECTED(TTOrErr, Succeeded()); |
203 | XCOFFTracebackTable TT = *TTOrErr; |
204 | |
205 | EXPECT_EQ(TT.getNumberOfFixedParms(), 3); |
206 | EXPECT_EQ(TT.getNumberOfFPParms(), 2); |
207 | EXPECT_TRUE(TT.hasVectorInfo()); |
208 | EXPECT_TRUE(TT.hasExtensionTable()); |
209 | |
210 | ASSERT_TRUE(TT.getParmsType()); |
211 | EXPECT_EQ(*TT.getParmsType(), "v, i, f, i, d, i, v" ); |
212 | |
213 | ASSERT_TRUE(TT.getVectorExt()); |
214 | TBVectorExt VecExt = *TT.getVectorExt(); |
215 | |
216 | EXPECT_EQ(VecExt.getNumberOfVRSaved(), 0); |
217 | EXPECT_TRUE(VecExt.isVRSavedOnStack()); |
218 | EXPECT_FALSE(VecExt.hasVarArgs()); |
219 | |
220 | EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u); |
221 | EXPECT_TRUE(VecExt.hasVMXInstruction()); |
222 | |
223 | EXPECT_EQ(VecExt.getVectorParmsInfo(), "vf, vf" ); |
224 | |
225 | ASSERT_TRUE(TT.getExtensionTable()); |
226 | EXPECT_EQ(*TT.getExtensionTable(), ExtendedTBTableFlag::TB_SSP_CANARY); |
227 | |
228 | EXPECT_EQ(Size, 47u); |
229 | } |
230 | |
231 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) { |
232 | const uint8_t TBTableData[] = { |
233 | 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc5, |
234 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, |
235 | 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, |
236 | 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90, |
237 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; |
238 | uint64_t Size = sizeof(TBTableData); |
239 | Expected<XCOFFTracebackTable> TTOrErr = |
240 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
241 | ASSERT_THAT_EXPECTED(TTOrErr, Succeeded()); |
242 | XCOFFTracebackTable TT = *TTOrErr; |
243 | |
244 | ASSERT_TRUE(TT.getParmsType()); |
245 | EXPECT_EQ(*TT.getParmsType(), "v, i, f, i, d, i, v, v" ); |
246 | |
247 | ASSERT_TRUE(TT.getVectorExt()); |
248 | TBVectorExt VecExt = *TT.getVectorExt(); |
249 | |
250 | EXPECT_EQ(VecExt.getNumberOfVRSaved(), 4); |
251 | EXPECT_FALSE(VecExt.isVRSavedOnStack()); |
252 | EXPECT_TRUE(VecExt.hasVarArgs()); |
253 | |
254 | EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u); |
255 | EXPECT_TRUE(VecExt.hasVMXInstruction()); |
256 | |
257 | EXPECT_EQ(VecExt.getVectorParmsInfo(), "vi, vs, vc" ); |
258 | |
259 | ASSERT_TRUE(TT.getExtensionTable()); |
260 | EXPECT_EQ(*TT.getExtensionTable(), ExtendedTBTableFlag::TB_SSP_CANARY); |
261 | |
262 | EXPECT_EQ(Size, 46u); |
263 | } |
264 | |
265 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) { |
266 | uint64_t Size = 6; |
267 | Expected<XCOFFTracebackTable> TTOrErr = |
268 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
269 | EXPECT_THAT_ERROR( |
270 | TTOrErr.takeError(), |
271 | FailedWithMessage( |
272 | "unexpected end of data at offset 0x6 while reading [0x0, 0x8)" )); |
273 | EXPECT_EQ(Size, 0u); |
274 | } |
275 | |
276 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtParmsType) { |
277 | uint64_t Size = 9; |
278 | Expected<XCOFFTracebackTable> TTOrErr = |
279 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
280 | EXPECT_THAT_ERROR( |
281 | TTOrErr.takeError(), |
282 | FailedWithMessage( |
283 | "unexpected end of data at offset 0x9 while reading [0x8, 0xc)" )); |
284 | EXPECT_EQ(Size, 8u); |
285 | } |
286 | |
287 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtTBOffset) { |
288 | uint64_t Size = 14; |
289 | Expected<XCOFFTracebackTable> TTOrErr = |
290 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
291 | EXPECT_THAT_ERROR( |
292 | TTOrErr.takeError(), |
293 | FailedWithMessage( |
294 | "unexpected end of data at offset 0xe while reading [0xc, 0x10)" )); |
295 | EXPECT_EQ(Size, 12u); |
296 | } |
297 | |
298 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtHandlerMask) { |
299 | uint8_t V[] = {0x00, 0x00, 0x22, 0xC0, 0x80, 0x00, 0x01, 0x05, 0x58, |
300 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07}; |
301 | uint64_t Size = sizeof(V); |
302 | Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(Ptr: V, Size); |
303 | EXPECT_THAT_ERROR( |
304 | TTOrErr.takeError(), |
305 | FailedWithMessage( |
306 | "unexpected end of data at offset 0x12 while reading [0x10, 0x14)" )); |
307 | EXPECT_EQ(Size, 16u); |
308 | } |
309 | |
310 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNumOfCtlAnchors) { |
311 | uint64_t Size = 19; |
312 | Expected<XCOFFTracebackTable> TTOrErr = |
313 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
314 | EXPECT_THAT_ERROR( |
315 | TTOrErr.takeError(), |
316 | FailedWithMessage( |
317 | "unexpected end of data at offset 0x13 while reading [0x10, 0x14)" )); |
318 | EXPECT_EQ(Size, 16u); |
319 | } |
320 | |
321 | TEST(XCOFFObjectFileTest, |
322 | XCOFFTracebackTableTruncatedAtControlledStorageInfoDisp) { |
323 | uint64_t Size = 21; |
324 | Expected<XCOFFTracebackTable> TTOrErr = |
325 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
326 | EXPECT_THAT_ERROR( |
327 | TTOrErr.takeError(), |
328 | FailedWithMessage( |
329 | "unexpected end of data at offset 0x15 while reading [0x14, 0x18)" )); |
330 | EXPECT_EQ(Size, 20u); |
331 | } |
332 | |
333 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNameLen) { |
334 | uint64_t Size = 29; |
335 | Expected<XCOFFTracebackTable> TTOrErr = |
336 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
337 | EXPECT_THAT_ERROR( |
338 | TTOrErr.takeError(), |
339 | FailedWithMessage( |
340 | "unexpected end of data at offset 0x1d while reading [0x1c, 0x1e)" )); |
341 | EXPECT_EQ(Size, 28u); |
342 | } |
343 | |
344 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtFunctionName) { |
345 | uint64_t Size = 36; |
346 | Expected<XCOFFTracebackTable> TTOrErr = |
347 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
348 | EXPECT_THAT_ERROR( |
349 | TTOrErr.takeError(), |
350 | FailedWithMessage( |
351 | "unexpected end of data at offset 0x24 while reading [0x1e, 0x25)" )); |
352 | EXPECT_EQ(Size, 30u); |
353 | } |
354 | |
355 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtAllocaUsed) { |
356 | uint64_t Size = 37; |
357 | Expected<XCOFFTracebackTable> TTOrErr = |
358 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
359 | EXPECT_THAT_ERROR( |
360 | TTOrErr.takeError(), |
361 | FailedWithMessage( |
362 | "unexpected end of data at offset 0x25 while reading [0x25, 0x26)" )); |
363 | EXPECT_EQ(Size, 37u); |
364 | } |
365 | |
366 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoData) { |
367 | uint64_t Size = 39; |
368 | Expected<XCOFFTracebackTable> TTOrErr = |
369 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
370 | |
371 | EXPECT_THAT_ERROR( |
372 | TTOrErr.takeError(), |
373 | FailedWithMessage( |
374 | "unexpected end of data at offset 0x27 while reading [0x26, 0x2c)" )); |
375 | EXPECT_EQ(Size, 38u); |
376 | } |
377 | |
378 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoParmsInfo) { |
379 | uint64_t Size = 43; |
380 | Expected<XCOFFTracebackTable> TTOrErr = |
381 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
382 | |
383 | EXPECT_THAT_ERROR( |
384 | TTOrErr.takeError(), |
385 | FailedWithMessage( |
386 | "unexpected end of data at offset 0x2b while reading [0x26, 0x2c)" )); |
387 | EXPECT_EQ(Size, 38u); |
388 | } |
389 | |
390 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtExtLongTBTable) { |
391 | uint64_t Size = 46; |
392 | Expected<XCOFFTracebackTable> TTOrErr = |
393 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
394 | |
395 | EXPECT_THAT_ERROR( |
396 | TTOrErr.takeError(), |
397 | FailedWithMessage( |
398 | "unexpected end of data at offset 0x2e while reading [0x2e, 0x2f)" )); |
399 | EXPECT_EQ(Size, 46u); |
400 | } |
401 | |
402 | TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef32) { |
403 | uint8_t XCOFF32Binary[] = { |
404 | // File header. |
405 | 0x01, 0xdf, 0x00, 0x01, 0x5f, 0x58, 0xf8, 0x95, 0x00, 0x00, 0x00, 0x3c, |
406 | 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, |
407 | |
408 | // Section header for empty .data section. |
409 | 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
410 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
411 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
412 | 0x00, 0x00, 0x00, 0x40, |
413 | |
414 | // Start of symbol table. |
415 | // C_File symbol. |
416 | 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
417 | 0xff, 0xfe, 0x00, 0x03, 0x67, 0x01, |
418 | // File Auxiliary Entry. |
419 | 0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
420 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
421 | |
422 | // Csect symbol. |
423 | 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
424 | 0x00, 0x01, 0x00, 0x00, 0x6b, 0x01, |
425 | // Csect auxiliary entry. |
426 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05, |
427 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
428 | |
429 | ArrayRef<uint8_t> XCOFF32Ref(XCOFF32Binary, sizeof(XCOFF32Binary)); |
430 | Expected<std::unique_ptr<ObjectFile>> XCOFFObjOrErr = |
431 | object::ObjectFile::createObjectFile( |
432 | Object: MemoryBufferRef(toStringRef(Input: XCOFF32Ref), "dummyXCOFF" ), |
433 | Type: file_magic::xcoff_object_32); |
434 | ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded()); |
435 | |
436 | const XCOFFObjectFile &File = *cast<XCOFFObjectFile>(Val: (*XCOFFObjOrErr).get()); |
437 | DataRefImpl Ref; |
438 | Ref.p = File.getSymbolEntryAddressByIndex(SymbolTableIndex: 2); |
439 | XCOFFSymbolRef SymRef = File.toSymbolRef(Ref); |
440 | Expected<XCOFFCsectAuxRef> CsectRefOrErr = SymRef.getXCOFFCsectAuxRef(); |
441 | ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded()); |
442 | |
443 | // Set csect symbol's auxiliary entry count to 0. |
444 | XCOFF32Binary[113] = 0; |
445 | Expected<XCOFFCsectAuxRef> ExpectErr = SymRef.getXCOFFCsectAuxRef(); |
446 | EXPECT_THAT_ERROR( |
447 | ExpectErr.takeError(), |
448 | FailedWithMessage( |
449 | "csect symbol \".data\" with index 2 contains no auxiliary entry" )); |
450 | } |
451 | |
452 | TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef64) { |
453 | uint8_t XCOFF64Binary[] = { |
454 | // File header. |
455 | 0x01, 0xf7, 0x00, 0x01, 0x5f, 0x59, 0x25, 0xeb, 0x00, 0x00, 0x00, 0x00, |
456 | 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
457 | |
458 | // Section header for empty .data section. |
459 | 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
460 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
461 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
462 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
463 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
464 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, |
465 | |
466 | // Start of symbol table. |
467 | // C_File symbol. |
468 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, |
469 | 0xff, 0xfe, 0x00, 0x02, 0x67, 0x01, |
470 | // File Auxiliary Entry. |
471 | 0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
472 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, |
473 | |
474 | // Csect symbol. |
475 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, |
476 | 0x00, 0x01, 0x00, 0x00, 0x6b, 0x01, |
477 | // Csect auxiliary entry. |
478 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05, |
479 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, |
480 | |
481 | // String table. |
482 | 0x00, 0x00, 0x00, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x2e, 0x64, |
483 | 0x61, 0x74, 0x61, 0x00}; |
484 | |
485 | ArrayRef<uint8_t> XCOFF64Ref(XCOFF64Binary, sizeof(XCOFF64Binary)); |
486 | Expected<std::unique_ptr<ObjectFile>> XCOFFObjOrErr = |
487 | object::ObjectFile::createObjectFile( |
488 | Object: MemoryBufferRef(toStringRef(Input: XCOFF64Ref), "dummyXCOFF" ), |
489 | Type: file_magic::xcoff_object_64); |
490 | ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded()); |
491 | |
492 | const XCOFFObjectFile &File = *cast<XCOFFObjectFile>(Val: (*XCOFFObjOrErr).get()); |
493 | DataRefImpl Ref; |
494 | Ref.p = File.getSymbolEntryAddressByIndex(SymbolTableIndex: 2); |
495 | XCOFFSymbolRef SymRef = File.toSymbolRef(Ref); |
496 | Expected<XCOFFCsectAuxRef> CsectRefOrErr = SymRef.getXCOFFCsectAuxRef(); |
497 | ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded()); |
498 | |
499 | // Inject incorrect auxiliary type value. |
500 | XCOFF64Binary[167] = static_cast<uint8_t>(XCOFF::AUX_SYM); |
501 | Expected<XCOFFCsectAuxRef> NotFoundErr = SymRef.getXCOFFCsectAuxRef(); |
502 | EXPECT_THAT_ERROR( |
503 | NotFoundErr.takeError(), |
504 | FailedWithMessage("a csect auxiliary entry has not been found for symbol " |
505 | "\".data\" with index 2" )); |
506 | |
507 | // Set csect symbol's auxiliary entry count to 0. |
508 | XCOFF64Binary[149] = 0; |
509 | Expected<XCOFFCsectAuxRef> ExpectErr = SymRef.getXCOFFCsectAuxRef(); |
510 | EXPECT_THAT_ERROR( |
511 | ExpectErr.takeError(), |
512 | FailedWithMessage( |
513 | "csect symbol \".data\" with index 2 contains no auxiliary entry" )); |
514 | } |
515 | |
516 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterType) { |
517 | const uint8_t TBTableData[] = {0x00, 0x00, 0x22, 0x40, 0x80, 0x00, 0x01, |
518 | 0x05, 0x58, 0x00, 0x10, 0x00, 0x00, 0x00, |
519 | 0x00, 0x40, 0x00, 0x07, 0x61, 0x64, 0x64, |
520 | 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00}; |
521 | uint64_t Size = 28; |
522 | Expected<XCOFFTracebackTable> TTOrErr = |
523 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
524 | |
525 | EXPECT_THAT_ERROR( |
526 | TTOrErr.takeError(), |
527 | FailedWithMessage("ParmsType encodes can not map to ParmsNum parameters " |
528 | "in parseParmsType." )); |
529 | } |
530 | |
531 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterTypeWithVecInfo) { |
532 | const uint8_t TBTableData[] = { |
533 | 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, |
534 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, |
535 | 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, |
536 | 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90, |
537 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; |
538 | uint64_t Size = 46; |
539 | Expected<XCOFFTracebackTable> TTOrErr = |
540 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
541 | |
542 | EXPECT_THAT_ERROR( |
543 | TTOrErr.takeError(), |
544 | FailedWithMessage("ParmsType encodes can not map to ParmsNum parameters " |
545 | "in parseParmsTypeWithVecInfo." )); |
546 | } |
547 | |
548 | TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtVecParameterType) { |
549 | const uint8_t TBTableData[] = { |
550 | 0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, |
551 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, |
552 | 0x05, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, |
553 | 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x11, 0x07, 0x90, |
554 | 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00}; |
555 | uint64_t Size = 46; |
556 | Expected<XCOFFTracebackTable> TTOrErr = |
557 | XCOFFTracebackTable::create(Ptr: TBTableData, Size); |
558 | |
559 | EXPECT_THAT_ERROR(TTOrErr.takeError(), |
560 | FailedWithMessage("ParmsType encodes more than ParmsNum " |
561 | "parameters in parseVectorParmsType." )); |
562 | } |
563 | |