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