561 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			561 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- XCOFFObjectFileTest.cpp - Tests for XCOFFObjectFile ----------------===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/Object/ELFObjectFile.h"
 | |
| #include "llvm/Object/XCOFFObjectFile.h"
 | |
| #include "llvm/Testing/Support/Error.h"
 | |
| #include "gtest/gtest.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace llvm::object;
 | |
| using namespace llvm::XCOFF;
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFObjectType) {
 | |
|   // Create an arbitrary object of a non-XCOFF type and test that
 | |
|   // dyn_cast<XCOFFObjectFile> returns null for it.
 | |
|   char Buf[sizeof(typename ELF64LE::Ehdr)] = {};
 | |
|   memcpy(Buf, "\177ELF", 4);
 | |
| 
 | |
|   auto *EHdr = reinterpret_cast<typename ELF64LE::Ehdr *>(Buf);
 | |
|   EHdr->e_ident[llvm::ELF::EI_CLASS] = llvm::ELF::ELFCLASS64;
 | |
|   EHdr->e_ident[llvm::ELF::EI_DATA] = llvm::ELF::ELFDATA2LSB;
 | |
| 
 | |
|   MemoryBufferRef Source(StringRef(Buf, sizeof(Buf)), "non-XCOFF");
 | |
|   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
 | |
|       ObjectFile::createObjectFile(Source);
 | |
|   ASSERT_THAT_EXPECTED(ObjOrErr, Succeeded());
 | |
| 
 | |
|   EXPECT_TRUE(dyn_cast<XCOFFObjectFile>((*ObjOrErr).get()) == nullptr);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, doesXCOFFTracebackTableBegin) {
 | |
|   EXPECT_TRUE(doesXCOFFTracebackTableBegin({0, 0, 0, 0}));
 | |
|   EXPECT_TRUE(doesXCOFFTracebackTableBegin({0, 0, 0, 0, 1}));
 | |
|   EXPECT_FALSE(doesXCOFFTracebackTableBegin({0, 0, 0, 1}));
 | |
|   EXPECT_FALSE(doesXCOFFTracebackTableBegin({0, 0, 0}));
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIGeneral) {
 | |
|   uint8_t V[] = {0x00, 0x00, 0x22, 0x40, 0x80, 0x00, 0x01, 0x05, 0x58, 0x00,
 | |
|                  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x61, 0x64,
 | |
|                  0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
 | |
|   uint64_t Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
 | |
|   XCOFFTracebackTable TT = *TTOrErr;
 | |
| 
 | |
|   EXPECT_EQ(TT.getVersion(), 0);
 | |
| 
 | |
|   EXPECT_EQ(TT.getLanguageID(), 0);
 | |
| 
 | |
|   EXPECT_FALSE(TT.isGlobalLinkage());
 | |
|   EXPECT_FALSE(TT.isOutOfLineEpilogOrPrologue());
 | |
|   EXPECT_TRUE(TT.hasTraceBackTableOffset());
 | |
|   EXPECT_FALSE(TT.isInternalProcedure());
 | |
|   EXPECT_FALSE(TT.hasControlledStorage());
 | |
|   EXPECT_FALSE(TT.isTOCless());
 | |
|   EXPECT_TRUE(TT.isFloatingPointPresent());
 | |
|   EXPECT_FALSE(TT.isFloatingPointOperationLogOrAbortEnabled());
 | |
| 
 | |
|   EXPECT_FALSE(TT.isInterruptHandler());
 | |
|   EXPECT_TRUE(TT.isFuncNamePresent());
 | |
|   EXPECT_FALSE(TT.isAllocaUsed());
 | |
|   EXPECT_EQ(TT.getOnConditionDirective(), 0);
 | |
|   EXPECT_FALSE(TT.isCRSaved());
 | |
|   EXPECT_FALSE(TT.isLRSaved());
 | |
| 
 | |
|   EXPECT_TRUE(TT.isBackChainStored());
 | |
|   EXPECT_FALSE(TT.isFixup());
 | |
|   EXPECT_EQ(TT.getNumOfFPRsSaved(), 0);
 | |
| 
 | |
|   EXPECT_FALSE(TT.hasExtensionTable());
 | |
|   EXPECT_FALSE(TT.hasVectorInfo());
 | |
|   EXPECT_EQ(TT.getNumOfGPRsSaved(), 0);
 | |
| 
 | |
|   EXPECT_EQ(TT.getNumberOfFixedParms(), 1);
 | |
| 
 | |
|   EXPECT_EQ(TT.getNumberOfFPParms(), 2);
 | |
|   EXPECT_TRUE(TT.hasParmsOnStack());
 | |
| 
 | |
|   ASSERT_TRUE(TT.getParmsType());
 | |
|   EXPECT_EQ(TT.getParmsType().getValue(), "i, f, d");
 | |
| 
 | |
|   ASSERT_TRUE(TT.getTraceBackTableOffset());
 | |
|   EXPECT_EQ(TT.getTraceBackTableOffset().getValue(), 64u);
 | |
| 
 | |
|   EXPECT_FALSE(TT.getHandlerMask());
 | |
| 
 | |
|   ASSERT_TRUE(TT.getFunctionName());
 | |
|   EXPECT_EQ(TT.getFunctionName().getValue(), "add_all");
 | |
|   EXPECT_EQ(TT.getFunctionName().getValue().size(), 7u);
 | |
| 
 | |
|   EXPECT_FALSE(TT.getAllocaRegister());
 | |
|   EXPECT_EQ(Size, 25u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIParmsType) {
 | |
|   uint8_t V[] = {0x01, 0x02, 0xA2, 0x40, 0x80, 0x00, 0x02, 0x07, 0x2B, 0x00,
 | |
|                  0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07, 0x61, 0x64,
 | |
|                  0x64, 0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
 | |
|   uint64_t Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
 | |
| 
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
 | |
|   XCOFFTracebackTable TT = *TTOrErr;
 | |
|   EXPECT_EQ(TT.getVersion(), 1);
 | |
|   EXPECT_EQ(TT.getLanguageID(), 2);
 | |
| 
 | |
|   EXPECT_TRUE(TT.isGlobalLinkage());
 | |
|   EXPECT_EQ(TT.getNumberOfFixedParms(), 2);
 | |
| 
 | |
|   EXPECT_EQ(TT.getNumberOfFPParms(), 3);
 | |
| 
 | |
|   ASSERT_TRUE(TT.getParmsType());
 | |
|   EXPECT_EQ(TT.getParmsType().getValue(), "i, i, f, f, d");
 | |
| 
 | |
|   V[8] = 0xAC;
 | |
|   Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr1 = XCOFFTracebackTable::create(V, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr1, Succeeded());
 | |
|   XCOFFTracebackTable TT1 = *TTOrErr1;
 | |
|   ASSERT_TRUE(TT1.getParmsType());
 | |
|   EXPECT_EQ(TT1.getParmsType().getValue(), "f, f, d, i, i");
 | |
| 
 | |
|   V[8] = 0xD4;
 | |
|   Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr2 = XCOFFTracebackTable::create(V, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr2, Succeeded());
 | |
|   XCOFFTracebackTable TT2 = *TTOrErr2;
 | |
|   ASSERT_TRUE(TT2.getParmsType());
 | |
|   EXPECT_EQ(TT2.getParmsType().getValue(), "d, i, f, f, i");
 | |
| 
 | |
|   V[6] = 0x01;
 | |
|   Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr3 = XCOFFTracebackTable::create(V, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr3, Succeeded());
 | |
|   XCOFFTracebackTable TT3 = *TTOrErr3;
 | |
|   ASSERT_TRUE(TT3.getParmsType());
 | |
|   EXPECT_EQ(TT3.getParmsType().getValue(), "d, i, f, f");
 | |
| 
 | |
|   V[6] = 0x04;
 | |
|   V[7] = 0x1E;
 | |
|   V[8] = 0xAC;
 | |
|   V[9] = 0xAA;
 | |
|   V[10] = 0xAA;
 | |
|   V[11] = 0xAA;
 | |
|   Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr4 = XCOFFTracebackTable::create(V, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr4, Succeeded());
 | |
|   XCOFFTracebackTable TT4 = *TTOrErr4;
 | |
|   ASSERT_TRUE(TT4.getParmsType());
 | |
|   EXPECT_EQ(TT4.getParmsType().getValue(),
 | |
|             "f, f, d, i, i, f, f, f, f, f, f, f, f, f, f, f, f, ...");
 | |
| }
 | |
| 
 | |
| const uint8_t TBTableData[] = {
 | |
|     0x00, 0x00, 0x2A, 0x60, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc4, 0x00, 0x00,
 | |
|     0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
 | |
|     0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
 | |
|     0x6c, 0x1f, 0x02, 0x05, 0xf0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIControlledStorageInfoDisp) {
 | |
|   uint64_t Size = sizeof(TBTableData);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
 | |
|   XCOFFTracebackTable TT = *TTOrErr;
 | |
|   EXPECT_TRUE(TT.hasControlledStorage());
 | |
|   ASSERT_TRUE(TT.getNumOfCtlAnchors());
 | |
|   EXPECT_EQ(TT.getNumOfCtlAnchors().getValue(), 2u);
 | |
| 
 | |
|   ASSERT_TRUE(TT.getControlledStorageInfoDisp());
 | |
| 
 | |
|   SmallVector<uint32_t, 8> Disp = TT.getControlledStorageInfoDisp().getValue();
 | |
| 
 | |
|   ASSERT_EQ(Disp.size(), 2UL);
 | |
|   EXPECT_EQ(Disp[0], 0x05050000u);
 | |
|   EXPECT_EQ(Disp[1], 0x06060000u);
 | |
|   EXPECT_EQ(Size, 45u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIAllocaRegister) {
 | |
|   uint64_t Size = sizeof(TBTableData);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
 | |
|   XCOFFTracebackTable TT = *TTOrErr;
 | |
|   ASSERT_TRUE(TT.getAllocaRegister());
 | |
|   EXPECT_EQ(TT.getAllocaRegister().getValue(), 31u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo) {
 | |
| 
 | |
|   uint64_t Size = sizeof(TBTableData);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
 | |
|   XCOFFTracebackTable TT = *TTOrErr;
 | |
| 
 | |
|   EXPECT_EQ(TT.getNumberOfFixedParms(), 3);
 | |
|   EXPECT_EQ(TT.getNumberOfFPParms(), 2);
 | |
|   EXPECT_TRUE(TT.hasVectorInfo());
 | |
|   EXPECT_TRUE(TT.hasExtensionTable());
 | |
| 
 | |
|   ASSERT_TRUE(TT.getParmsType());
 | |
|   EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i, v");
 | |
| 
 | |
|   ASSERT_TRUE(TT.getVectorExt());
 | |
|   TBVectorExt VecExt = TT.getVectorExt().getValue();
 | |
| 
 | |
|   EXPECT_EQ(VecExt.getNumberOfVRSaved(), 0);
 | |
|   EXPECT_TRUE(VecExt.isVRSavedOnStack());
 | |
|   EXPECT_FALSE(VecExt.hasVarArgs());
 | |
| 
 | |
|   EXPECT_EQ(VecExt.getNumberOfVectorParms(), 2u);
 | |
|   EXPECT_TRUE(VecExt.hasVMXInstruction());
 | |
| 
 | |
|   EXPECT_EQ(VecExt.getVectorParmsInfo(), "vf, vf");
 | |
| 
 | |
|   ASSERT_TRUE(TT.getExtensionTable());
 | |
|   EXPECT_EQ(TT.getExtensionTable().getValue(),
 | |
|             ExtendedTBTableFlag::TB_SSP_CANARY);
 | |
| 
 | |
|   EXPECT_EQ(Size, 45u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableAPIHasVectorInfo1) {
 | |
|   const uint8_t TBTableData[] = {
 | |
|       0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc5, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
 | |
|       0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
 | |
|       0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
 | |
|   uint64_t Size = sizeof(TBTableData);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   ASSERT_THAT_EXPECTED(TTOrErr, Succeeded());
 | |
|   XCOFFTracebackTable TT = *TTOrErr;
 | |
| 
 | |
|   ASSERT_TRUE(TT.getParmsType());
 | |
|   EXPECT_EQ(TT.getParmsType().getValue(), "v, i, f, i, d, i, v, v");
 | |
| 
 | |
|   ASSERT_TRUE(TT.getVectorExt());
 | |
|   TBVectorExt VecExt = TT.getVectorExt().getValue();
 | |
| 
 | |
|   EXPECT_EQ(VecExt.getNumberOfVRSaved(), 4);
 | |
|   EXPECT_FALSE(VecExt.isVRSavedOnStack());
 | |
|   EXPECT_TRUE(VecExt.hasVarArgs());
 | |
| 
 | |
|   EXPECT_EQ(VecExt.getNumberOfVectorParms(), 3u);
 | |
|   EXPECT_TRUE(VecExt.hasVMXInstruction());
 | |
| 
 | |
|   EXPECT_EQ(VecExt.getVectorParmsInfo(), "vi, vs, vc");
 | |
| 
 | |
|   ASSERT_TRUE(TT.getExtensionTable());
 | |
|   EXPECT_EQ(TT.getExtensionTable().getValue(),
 | |
|             ExtendedTBTableFlag::TB_SSP_CANARY);
 | |
| 
 | |
|   EXPECT_EQ(Size, 44u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtMandatory) {
 | |
|   uint64_t Size = 6;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x6 while reading [0x0, 0x8)"));
 | |
|   EXPECT_EQ(Size, 0u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtParmsType) {
 | |
|   uint64_t Size = 9;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x9 while reading [0x8, 0xc)"));
 | |
|   EXPECT_EQ(Size, 8u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtTBOffset) {
 | |
|   uint64_t Size = 14;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0xe while reading [0xc, 0x10)"));
 | |
|   EXPECT_EQ(Size, 12u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtHandlerMask) {
 | |
|   uint8_t V[] = {0x00, 0x00, 0x22, 0xC0, 0x80, 0x00, 0x01, 0x05, 0x58,
 | |
|                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x07};
 | |
|   uint64_t Size = sizeof(V);
 | |
|   Expected<XCOFFTracebackTable> TTOrErr = XCOFFTracebackTable::create(V, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x12 while reading [0x10, 0x14)"));
 | |
|   EXPECT_EQ(Size, 16u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNumOfCtlAnchors) {
 | |
|   uint64_t Size = 19;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x13 while reading [0x10, 0x14)"));
 | |
|   EXPECT_EQ(Size, 16u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest,
 | |
|      XCOFFTracebackTableTruncatedAtControlledStorageInfoDisp) {
 | |
|   uint64_t Size = 21;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x15 while reading [0x14, 0x18)"));
 | |
|   EXPECT_EQ(Size, 20u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtNameLen) {
 | |
|   uint64_t Size = 29;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x1d while reading [0x1c, 0x1e)"));
 | |
|   EXPECT_EQ(Size, 28u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtFunctionName) {
 | |
|   uint64_t Size = 36;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x24 while reading [0x1e, 0x25)"));
 | |
|   EXPECT_EQ(Size, 30u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtAllocaUsed) {
 | |
|   uint64_t Size = 37;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x25 while reading [0x25, 0x26)"));
 | |
|   EXPECT_EQ(Size, 37u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoData) {
 | |
|   uint64_t Size = 39;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
| 
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x27 while reading [0x26, 0x2c)"));
 | |
|   EXPECT_EQ(Size, 38u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtVectorInfoParmsInfo) {
 | |
|   uint64_t Size = 43;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
| 
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x2b while reading [0x26, 0x2c)"));
 | |
|   EXPECT_EQ(Size, 38u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableTruncatedAtExtLongTBTable) {
 | |
|   uint64_t Size = 44;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
| 
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "unexpected end of data at offset 0x2c while reading [0x2c, 0x2d)"));
 | |
|   EXPECT_EQ(Size, 44u);
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef32) {
 | |
|   uint8_t XCOFF32Binary[] = {
 | |
|       // File header.
 | |
|       0x01, 0xdf, 0x00, 0x01, 0x5f, 0x58, 0xf8, 0x95, 0x00, 0x00, 0x00, 0x3c,
 | |
|       0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
 | |
| 
 | |
|       // Section header for empty .data section.
 | |
|       0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x40,
 | |
| 
 | |
|       // Start of symbol table.
 | |
|       // C_File symbol.
 | |
|       0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0xff, 0xfe, 0x00, 0x03, 0x67, 0x01,
 | |
|       // File Auxiliary Entry.
 | |
|       0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
| 
 | |
|       // Csect symbol.
 | |
|       0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x01, 0x00, 0x00, 0x6b, 0x01,
 | |
|       // Csect auxiliary entry.
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 | |
| 
 | |
|   ArrayRef<uint8_t> XCOFF32Ref(XCOFF32Binary, sizeof(XCOFF32Binary));
 | |
|   Expected<std::unique_ptr<ObjectFile>> XCOFFObjOrErr =
 | |
|       object::ObjectFile::createObjectFile(
 | |
|           MemoryBufferRef(toStringRef(XCOFF32Ref), "dummyXCOFF"),
 | |
|           file_magic::xcoff_object_32);
 | |
|   ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded());
 | |
| 
 | |
|   const XCOFFObjectFile &File = *cast<XCOFFObjectFile>((*XCOFFObjOrErr).get());
 | |
|   DataRefImpl Ref;
 | |
|   Ref.p = File.getSymbolEntryAddressByIndex(2);
 | |
|   XCOFFSymbolRef SymRef = File.toSymbolRef(Ref);
 | |
|   Expected<XCOFFCsectAuxRef> CsectRefOrErr = SymRef.getXCOFFCsectAuxRef();
 | |
|   ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded());
 | |
| 
 | |
|   // Set csect symbol's auxiliary entry count to 0.
 | |
|   XCOFF32Binary[113] = 0;
 | |
|   Expected<XCOFFCsectAuxRef> ExpectErr = SymRef.getXCOFFCsectAuxRef();
 | |
|   EXPECT_THAT_ERROR(
 | |
|       ExpectErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "csect symbol \".data\" with index 2 contains no auxiliary entry"));
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFGetCsectAuxRef64) {
 | |
|   uint8_t XCOFF64Binary[] = {
 | |
|       // File header.
 | |
|       0x01, 0xf7, 0x00, 0x01, 0x5f, 0x59, 0x25, 0xeb, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
 | |
| 
 | |
|       // Section header for empty .data section.
 | |
|       0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
 | |
| 
 | |
|       // Start of symbol table.
 | |
|       // C_File symbol.
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
 | |
|       0xff, 0xfe, 0x00, 0x02, 0x67, 0x01,
 | |
|       // File Auxiliary Entry.
 | |
|       0x61, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
 | |
| 
 | |
|       // Csect symbol.
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
 | |
|       0x00, 0x01, 0x00, 0x00, 0x6b, 0x01,
 | |
|       // Csect auxiliary entry.
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x05,
 | |
|       0x00, 0x00, 0x00, 0x00, 0x00, 0xfb,
 | |
| 
 | |
|       // String table.
 | |
|       0x00, 0x00, 0x00, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x2e, 0x64,
 | |
|       0x61, 0x74, 0x61, 0x00};
 | |
| 
 | |
|   ArrayRef<uint8_t> XCOFF64Ref(XCOFF64Binary, sizeof(XCOFF64Binary));
 | |
|   Expected<std::unique_ptr<ObjectFile>> XCOFFObjOrErr =
 | |
|       object::ObjectFile::createObjectFile(
 | |
|           MemoryBufferRef(toStringRef(XCOFF64Ref), "dummyXCOFF"),
 | |
|           file_magic::xcoff_object_64);
 | |
|   ASSERT_THAT_EXPECTED(XCOFFObjOrErr, Succeeded());
 | |
| 
 | |
|   const XCOFFObjectFile &File = *cast<XCOFFObjectFile>((*XCOFFObjOrErr).get());
 | |
|   DataRefImpl Ref;
 | |
|   Ref.p = File.getSymbolEntryAddressByIndex(2);
 | |
|   XCOFFSymbolRef SymRef = File.toSymbolRef(Ref);
 | |
|   Expected<XCOFFCsectAuxRef> CsectRefOrErr = SymRef.getXCOFFCsectAuxRef();
 | |
|   ASSERT_THAT_EXPECTED(CsectRefOrErr, Succeeded());
 | |
| 
 | |
|   // Inject incorrect auxiliary type value.
 | |
|   XCOFF64Binary[167] = static_cast<uint8_t>(XCOFF::AUX_SYM);
 | |
|   Expected<XCOFFCsectAuxRef> NotFoundErr = SymRef.getXCOFFCsectAuxRef();
 | |
|   EXPECT_THAT_ERROR(
 | |
|       NotFoundErr.takeError(),
 | |
|       FailedWithMessage("a csect auxiliary entry has not been found for symbol "
 | |
|                         "\".data\" with index 2"));
 | |
| 
 | |
|   // Set csect symbol's auxiliary entry count to 0.
 | |
|   XCOFF64Binary[149] = 0;
 | |
|   Expected<XCOFFCsectAuxRef> ExpectErr = SymRef.getXCOFFCsectAuxRef();
 | |
|   EXPECT_THAT_ERROR(
 | |
|       ExpectErr.takeError(),
 | |
|       FailedWithMessage(
 | |
|           "csect symbol \".data\" with index 2 contains no auxiliary entry"));
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterType) {
 | |
|   const uint8_t TBTableData[] = {0x00, 0x00, 0x22, 0x40, 0x80, 0x00, 0x01,
 | |
|                                  0x05, 0x58, 0x00, 0x10, 0x00, 0x00, 0x00,
 | |
|                                  0x00, 0x40, 0x00, 0x07, 0x61, 0x64, 0x64,
 | |
|                                  0x5f, 0x61, 0x6c, 0x6c, 0x00, 0x00, 0x00};
 | |
|   uint64_t Size = 28;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
| 
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage("ParmsType encodes can not map to ParmsNum parameters "
 | |
|                         "in parseParmsType."));
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtParameterTypeWithVecInfo) {
 | |
|   const uint8_t TBTableData[] = {
 | |
|       0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x10,
 | |
|       0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
 | |
|       0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
 | |
|       0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
 | |
|   uint64_t Size = 44;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
| 
 | |
|   EXPECT_THAT_ERROR(
 | |
|       TTOrErr.takeError(),
 | |
|       FailedWithMessage("ParmsType encodes can not map to ParmsNum parameters "
 | |
|                         "in parseParmsTypeWithVecInfo."));
 | |
| }
 | |
| 
 | |
| TEST(XCOFFObjectFileTest, XCOFFTracebackTableErrorAtVecParameterType) {
 | |
|   const uint8_t TBTableData[] = {
 | |
|       0x00, 0x00, 0x2A, 0x40, 0x80, 0xc0, 0x03, 0x05, 0x48, 0xc0, 0x00, 0x00,
 | |
|       0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x05, 0x05, 0x00, 0x00,
 | |
|       0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x61, 0x64, 0x64, 0x5f, 0x61, 0x6c,
 | |
|       0x6c, 0x11, 0x07, 0x90, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00};
 | |
|   uint64_t Size = 44;
 | |
|   Expected<XCOFFTracebackTable> TTOrErr =
 | |
|       XCOFFTracebackTable::create(TBTableData, Size);
 | |
| 
 | |
|   EXPECT_THAT_ERROR(TTOrErr.takeError(),
 | |
|                     FailedWithMessage("ParmsType encodes more than ParmsNum "
 | |
|                                       "parameters in parseVectorParmsType."));
 | |
| }
 |