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(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 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(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 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 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 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 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.geNumberOfVRSaved(), 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 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.geNumberOfVRSaved(), 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 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 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 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 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 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 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 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 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 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 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 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 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