1 //===--- XCOFFObjectFile.cpp - XCOFF object file implementation -----------===// 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 // This file defines the XCOFFObjectFile class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Object/XCOFFObjectFile.h" 14 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/Support/Compiler.h" 16 #include "llvm/Support/DataExtractor.h" 17 #include "llvm/TargetParser/SubtargetFeature.h" 18 #include <cstddef> 19 #include <cstring> 20 21 namespace llvm { 22 23 using namespace XCOFF; 24 25 namespace object { 26 27 static const uint8_t FunctionSym = 0x20; 28 static const uint16_t NoRelMask = 0x0001; 29 static const size_t SymbolAuxTypeOffset = 17; 30 31 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer 32 // 'M'. Returns a pointer to the underlying object on success. 33 template <typename T> 34 static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, 35 const uint64_t Size = sizeof(T)) { 36 uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr); 37 if (Error E = Binary::checkOffset(M, Addr, Size)) 38 return std::move(E); 39 return reinterpret_cast<const T *>(Addr); 40 } 41 42 static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { 43 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + 44 Offset); 45 } 46 47 template <typename T> static const T *viewAs(uintptr_t in) { 48 return reinterpret_cast<const T *>(in); 49 } 50 51 static StringRef generateXCOFFFixedNameStringRef(const char *Name) { 52 auto NulCharPtr = 53 static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); 54 return NulCharPtr ? StringRef(Name, NulCharPtr - Name) 55 : StringRef(Name, XCOFF::NameSize); 56 } 57 58 template <typename T> StringRef XCOFFSectionHeader<T>::getName() const { 59 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 60 return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name); 61 } 62 63 template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const { 64 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 65 return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask; 66 } 67 68 template <typename T> 69 uint32_t XCOFFSectionHeader<T>::getSectionSubtype() const { 70 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 71 return DerivedXCOFFSectionHeader.Flags & ~SectionFlagsTypeMask; 72 } 73 74 template <typename T> 75 bool XCOFFSectionHeader<T>::isReservedSectionType() const { 76 return getSectionType() & SectionFlagsReservedMask; 77 } 78 79 template <typename AddressType> 80 bool XCOFFRelocation<AddressType>::isRelocationSigned() const { 81 return Info & XR_SIGN_INDICATOR_MASK; 82 } 83 84 template <typename AddressType> 85 bool XCOFFRelocation<AddressType>::isFixupIndicated() const { 86 return Info & XR_FIXUP_INDICATOR_MASK; 87 } 88 89 template <typename AddressType> 90 uint8_t XCOFFRelocation<AddressType>::getRelocatedLength() const { 91 // The relocation encodes the bit length being relocated minus 1. Add back 92 // the 1 to get the actual length being relocated. 93 return (Info & XR_BIASED_LENGTH_MASK) + 1; 94 } 95 96 template struct LLVM_EXPORT_TEMPLATE ExceptionSectionEntry<support::ubig32_t>; 97 template struct LLVM_EXPORT_TEMPLATE ExceptionSectionEntry<support::ubig64_t>; 98 99 template <typename T> 100 Expected<StringRef> getLoaderSecSymNameInStrTbl(const T *LoaderSecHeader, 101 uint64_t Offset) { 102 if (LoaderSecHeader->LengthOfStrTbl > Offset) 103 return (reinterpret_cast<const char *>(LoaderSecHeader) + 104 LoaderSecHeader->OffsetToStrTbl + Offset); 105 106 return createError("entry with offset 0x" + Twine::utohexstr(Offset) + 107 " in the loader section's string table with size 0x" + 108 Twine::utohexstr(LoaderSecHeader->LengthOfStrTbl) + 109 " is invalid"); 110 } 111 112 Expected<StringRef> LoaderSectionSymbolEntry32::getSymbolName( 113 const LoaderSectionHeader32 *LoaderSecHeader32) const { 114 const NameOffsetInStrTbl *NameInStrTbl = 115 reinterpret_cast<const NameOffsetInStrTbl *>(SymbolName); 116 if (NameInStrTbl->IsNameInStrTbl != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 117 return generateXCOFFFixedNameStringRef(SymbolName); 118 119 return getLoaderSecSymNameInStrTbl(LoaderSecHeader32, NameInStrTbl->Offset); 120 } 121 122 Expected<StringRef> LoaderSectionSymbolEntry64::getSymbolName( 123 const LoaderSectionHeader64 *LoaderSecHeader64) const { 124 return getLoaderSecSymNameInStrTbl(LoaderSecHeader64, Offset); 125 } 126 127 uintptr_t 128 XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, 129 uint32_t Distance) { 130 return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize); 131 } 132 133 const XCOFF::SymbolAuxType * 134 XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const { 135 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 136 return viewAs<XCOFF::SymbolAuxType>( 137 getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset)); 138 } 139 140 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, 141 uintptr_t TableAddress) const { 142 if (Addr < TableAddress) 143 report_fatal_error("Section header outside of section header table."); 144 145 uintptr_t Offset = Addr - TableAddress; 146 if (Offset >= getSectionHeaderSize() * getNumberOfSections()) 147 report_fatal_error("Section header outside of section header table."); 148 149 if (Offset % getSectionHeaderSize() != 0) 150 report_fatal_error( 151 "Section header pointer does not point to a valid section header."); 152 } 153 154 const XCOFFSectionHeader32 * 155 XCOFFObjectFile::toSection32(DataRefImpl Ref) const { 156 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 157 #ifndef NDEBUG 158 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 159 #endif 160 return viewAs<XCOFFSectionHeader32>(Ref.p); 161 } 162 163 const XCOFFSectionHeader64 * 164 XCOFFObjectFile::toSection64(DataRefImpl Ref) const { 165 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 166 #ifndef NDEBUG 167 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 168 #endif 169 return viewAs<XCOFFSectionHeader64>(Ref.p); 170 } 171 172 XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const { 173 assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); 174 #ifndef NDEBUG 175 checkSymbolEntryPointer(Ref.p); 176 #endif 177 return XCOFFSymbolRef(Ref, this); 178 } 179 180 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { 181 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 182 return static_cast<const XCOFFFileHeader32 *>(FileHeader); 183 } 184 185 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { 186 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 187 return static_cast<const XCOFFFileHeader64 *>(FileHeader); 188 } 189 190 const XCOFFAuxiliaryHeader32 *XCOFFObjectFile::auxiliaryHeader32() const { 191 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 192 return static_cast<const XCOFFAuxiliaryHeader32 *>(AuxiliaryHeader); 193 } 194 195 const XCOFFAuxiliaryHeader64 *XCOFFObjectFile::auxiliaryHeader64() const { 196 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 197 return static_cast<const XCOFFAuxiliaryHeader64 *>(AuxiliaryHeader); 198 } 199 200 template <typename T> const T *XCOFFObjectFile::sectionHeaderTable() const { 201 return static_cast<const T *>(SectionHeaderTable); 202 } 203 204 const XCOFFSectionHeader32 * 205 XCOFFObjectFile::sectionHeaderTable32() const { 206 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 207 return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); 208 } 209 210 const XCOFFSectionHeader64 * 211 XCOFFObjectFile::sectionHeaderTable64() const { 212 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 213 return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); 214 } 215 216 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 217 uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress( 218 Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1); 219 #ifndef NDEBUG 220 // This function is used by basic_symbol_iterator, which allows to 221 // point to the end-of-symbol-table address. 222 if (NextSymbolAddr != getEndOfSymbolTableAddress()) 223 checkSymbolEntryPointer(NextSymbolAddr); 224 #endif 225 Symb.p = NextSymbolAddr; 226 } 227 228 Expected<StringRef> 229 XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { 230 // The byte offset is relative to the start of the string table. 231 // A byte offset value of 0 is a null or zero-length symbol 232 // name. A byte offset in the range 1 to 3 (inclusive) points into the length 233 // field; as a soft-error recovery mechanism, we treat such cases as having an 234 // offset of 0. 235 if (Offset < 4) 236 return StringRef(nullptr, 0); 237 238 if (StringTable.Data != nullptr && StringTable.Size > Offset) 239 return (StringTable.Data + Offset); 240 241 return createError("entry with offset 0x" + Twine::utohexstr(Offset) + 242 " in a string table with size 0x" + 243 Twine::utohexstr(StringTable.Size) + " is invalid"); 244 } 245 246 StringRef XCOFFObjectFile::getStringTable() const { 247 // If the size is less than or equal to 4, then the string table contains no 248 // string data. 249 return StringRef(StringTable.Data, 250 StringTable.Size <= 4 ? 0 : StringTable.Size); 251 } 252 253 Expected<StringRef> 254 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { 255 if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 256 return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); 257 return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); 258 } 259 260 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 261 return toSymbolRef(Symb).getName(); 262 } 263 264 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 265 return toSymbolRef(Symb).getValue(); 266 } 267 268 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 269 return toSymbolRef(Symb).getValue(); 270 } 271 272 uint32_t XCOFFObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 273 uint64_t Result = 0; 274 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); 275 if (XCOFFSym.isCsectSymbol()) { 276 Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = 277 XCOFFSym.getXCOFFCsectAuxRef(); 278 if (!CsectAuxRefOrError) 279 // TODO: report the error up the stack. 280 consumeError(CsectAuxRefOrError.takeError()); 281 else 282 Result = 1ULL << CsectAuxRefOrError.get().getAlignmentLog2(); 283 } 284 return Result; 285 } 286 287 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 288 uint64_t Result = 0; 289 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); 290 if (XCOFFSym.isCsectSymbol()) { 291 Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = 292 XCOFFSym.getXCOFFCsectAuxRef(); 293 if (!CsectAuxRefOrError) 294 // TODO: report the error up the stack. 295 consumeError(CsectAuxRefOrError.takeError()); 296 else { 297 XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get(); 298 assert(CsectAuxRef.getSymbolType() == XCOFF::XTY_CM); 299 Result = CsectAuxRef.getSectionOrLength(); 300 } 301 } 302 return Result; 303 } 304 305 Expected<SymbolRef::Type> 306 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 307 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); 308 309 Expected<bool> IsFunction = XCOFFSym.isFunction(); 310 if (!IsFunction) 311 return IsFunction.takeError(); 312 313 if (*IsFunction) 314 return SymbolRef::ST_Function; 315 316 if (XCOFF::C_FILE == XCOFFSym.getStorageClass()) 317 return SymbolRef::ST_File; 318 319 int16_t SecNum = XCOFFSym.getSectionNumber(); 320 if (SecNum <= 0) 321 return SymbolRef::ST_Other; 322 323 Expected<DataRefImpl> SecDRIOrErr = 324 getSectionByNum(XCOFFSym.getSectionNumber()); 325 326 if (!SecDRIOrErr) 327 return SecDRIOrErr.takeError(); 328 329 DataRefImpl SecDRI = SecDRIOrErr.get(); 330 331 Expected<StringRef> SymNameOrError = XCOFFSym.getName(); 332 if (SymNameOrError) { 333 // The "TOC" symbol is treated as SymbolRef::ST_Other. 334 if (SymNameOrError.get() == "TOC") 335 return SymbolRef::ST_Other; 336 337 // The symbol for a section name is treated as SymbolRef::ST_Other. 338 StringRef SecName; 339 if (is64Bit()) 340 SecName = XCOFFObjectFile::toSection64(SecDRIOrErr.get())->getName(); 341 else 342 SecName = XCOFFObjectFile::toSection32(SecDRIOrErr.get())->getName(); 343 344 if (SecName == SymNameOrError.get()) 345 return SymbolRef::ST_Other; 346 } else 347 return SymNameOrError.takeError(); 348 349 if (isSectionData(SecDRI) || isSectionBSS(SecDRI)) 350 return SymbolRef::ST_Data; 351 352 if (isDebugSection(SecDRI)) 353 return SymbolRef::ST_Debug; 354 355 return SymbolRef::ST_Other; 356 } 357 358 Expected<section_iterator> 359 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 360 const int16_t SectNum = toSymbolRef(Symb).getSectionNumber(); 361 362 if (isReservedSectionNumber(SectNum)) 363 return section_end(); 364 365 Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); 366 if (!ExpSec) 367 return ExpSec.takeError(); 368 369 return section_iterator(SectionRef(ExpSec.get(), this)); 370 } 371 372 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 373 const char *Ptr = reinterpret_cast<const char *>(Sec.p); 374 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); 375 } 376 377 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { 378 return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec)); 379 } 380 381 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 382 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 383 // with MSVC. 384 if (is64Bit()) 385 return toSection64(Sec)->VirtualAddress; 386 387 return toSection32(Sec)->VirtualAddress; 388 } 389 390 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 391 // Section numbers in XCOFF are numbered beginning at 1. A section number of 392 // zero is used to indicate that a symbol is being imported or is undefined. 393 if (is64Bit()) 394 return toSection64(Sec) - sectionHeaderTable64() + 1; 395 else 396 return toSection32(Sec) - sectionHeaderTable32() + 1; 397 } 398 399 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 400 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 401 // with MSVC. 402 if (is64Bit()) 403 return toSection64(Sec)->SectionSize; 404 405 return toSection32(Sec)->SectionSize; 406 } 407 408 Expected<ArrayRef<uint8_t>> 409 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 410 if (isSectionVirtual(Sec)) 411 return ArrayRef<uint8_t>(); 412 413 uint64_t OffsetToRaw; 414 if (is64Bit()) 415 OffsetToRaw = toSection64(Sec)->FileOffsetToRawData; 416 else 417 OffsetToRaw = toSection32(Sec)->FileOffsetToRawData; 418 419 const uint8_t * ContentStart = base() + OffsetToRaw; 420 uint64_t SectionSize = getSectionSize(Sec); 421 if (Error E = Binary::checkOffset( 422 Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) 423 return createError( 424 toString(std::move(E)) + ": section data with offset 0x" + 425 Twine::utohexstr(OffsetToRaw) + " and size 0x" + 426 Twine::utohexstr(SectionSize) + " goes past the end of the file"); 427 428 return ArrayRef(ContentStart, SectionSize); 429 } 430 431 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 432 // TODO: Copied from MC/XCOFFObjectWriter.cpp 433 // Sections other than DWARF section use DefaultSectionAlign as the default 434 // alignment, while DWARF sections have their own alignments. DWARF section 435 // alignment is bigger than DefaultSectionAlign. 436 if (isDebugSection(Sec)) 437 return 8; 438 return 4; 439 } 440 441 uint64_t XCOFFObjectFile::getSectionFileOffsetToRawData(DataRefImpl Sec) const { 442 if (is64Bit()) 443 return toSection64(Sec)->FileOffsetToRawData; 444 445 return toSection32(Sec)->FileOffsetToRawData; 446 } 447 448 Expected<uintptr_t> XCOFFObjectFile::getSectionFileOffsetToRawData( 449 XCOFF::SectionTypeFlags SectType) const { 450 DataRefImpl DRI = getSectionByType(SectType); 451 452 if (DRI.p == 0) // No section is not an error. 453 return 0; 454 455 uint64_t SectionOffset = getSectionFileOffsetToRawData(DRI); 456 uint64_t SizeOfSection = getSectionSize(DRI); 457 458 uintptr_t SectionStart = reinterpret_cast<uintptr_t>(base() + SectionOffset); 459 if (Error E = Binary::checkOffset(Data, SectionStart, SizeOfSection)) { 460 SmallString<32> UnknownType; 461 Twine(("<Unknown:") + Twine::utohexstr(SectType) + ">") 462 .toVector(UnknownType); 463 const char *SectionName = UnknownType.c_str(); 464 465 switch (SectType) { 466 #define ECASE(Value, String) \ 467 case XCOFF::Value: \ 468 SectionName = String; \ 469 break 470 471 ECASE(STYP_PAD, "pad"); 472 ECASE(STYP_DWARF, "dwarf"); 473 ECASE(STYP_TEXT, "text"); 474 ECASE(STYP_DATA, "data"); 475 ECASE(STYP_BSS, "bss"); 476 ECASE(STYP_EXCEPT, "expect"); 477 ECASE(STYP_INFO, "info"); 478 ECASE(STYP_TDATA, "tdata"); 479 ECASE(STYP_TBSS, "tbss"); 480 ECASE(STYP_LOADER, "loader"); 481 ECASE(STYP_DEBUG, "debug"); 482 ECASE(STYP_TYPCHK, "typchk"); 483 ECASE(STYP_OVRFLO, "ovrflo"); 484 #undef ECASE 485 } 486 return createError(toString(std::move(E)) + ": " + SectionName + 487 " section with offset 0x" + 488 Twine::utohexstr(SectionOffset) + " and size 0x" + 489 Twine::utohexstr(SizeOfSection) + 490 " goes past the end of the file"); 491 } 492 return SectionStart; 493 } 494 495 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 496 return false; 497 } 498 499 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 500 return getSectionFlags(Sec) & XCOFF::STYP_TEXT; 501 } 502 503 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 504 uint32_t Flags = getSectionFlags(Sec); 505 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 506 } 507 508 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 509 uint32_t Flags = getSectionFlags(Sec); 510 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 511 } 512 513 bool XCOFFObjectFile::isDebugSection(DataRefImpl Sec) const { 514 uint32_t Flags = getSectionFlags(Sec); 515 return Flags & (XCOFF::STYP_DEBUG | XCOFF::STYP_DWARF); 516 } 517 518 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 519 return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0 520 : toSection32(Sec)->FileOffsetToRawData == 0; 521 } 522 523 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 524 DataRefImpl Ret; 525 if (is64Bit()) { 526 const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); 527 auto RelocationsOrErr = 528 relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); 529 if (Error E = RelocationsOrErr.takeError()) { 530 // TODO: report the error up the stack. 531 consumeError(std::move(E)); 532 return relocation_iterator(RelocationRef()); 533 } 534 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 535 } else { 536 const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 537 auto RelocationsOrErr = 538 relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); 539 if (Error E = RelocationsOrErr.takeError()) { 540 // TODO: report the error up the stack. 541 consumeError(std::move(E)); 542 return relocation_iterator(RelocationRef()); 543 } 544 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 545 } 546 return relocation_iterator(RelocationRef(Ret, this)); 547 } 548 549 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 550 DataRefImpl Ret; 551 if (is64Bit()) { 552 const XCOFFSectionHeader64 *SectionEntPtr = toSection64(Sec); 553 auto RelocationsOrErr = 554 relocations<XCOFFSectionHeader64, XCOFFRelocation64>(*SectionEntPtr); 555 if (Error E = RelocationsOrErr.takeError()) { 556 // TODO: report the error up the stack. 557 consumeError(std::move(E)); 558 return relocation_iterator(RelocationRef()); 559 } 560 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 561 } else { 562 const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 563 auto RelocationsOrErr = 564 relocations<XCOFFSectionHeader32, XCOFFRelocation32>(*SectionEntPtr); 565 if (Error E = RelocationsOrErr.takeError()) { 566 // TODO: report the error up the stack. 567 consumeError(std::move(E)); 568 return relocation_iterator(RelocationRef()); 569 } 570 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 571 } 572 return relocation_iterator(RelocationRef(Ret, this)); 573 } 574 575 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 576 if (is64Bit()) 577 Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation64>(Rel.p) + 1); 578 else 579 Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); 580 } 581 582 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 583 if (is64Bit()) { 584 const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 585 const XCOFFSectionHeader64 *Sec64 = sectionHeaderTable64(); 586 const uint64_t RelocAddress = Reloc->VirtualAddress; 587 const uint16_t NumberOfSections = getNumberOfSections(); 588 for (uint16_t I = 0; I < NumberOfSections; ++I) { 589 // Find which section this relocation belongs to, and get the 590 // relocation offset relative to the start of the section. 591 if (Sec64->VirtualAddress <= RelocAddress && 592 RelocAddress < Sec64->VirtualAddress + Sec64->SectionSize) { 593 return RelocAddress - Sec64->VirtualAddress; 594 } 595 ++Sec64; 596 } 597 } else { 598 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 599 const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); 600 const uint32_t RelocAddress = Reloc->VirtualAddress; 601 const uint16_t NumberOfSections = getNumberOfSections(); 602 for (uint16_t I = 0; I < NumberOfSections; ++I) { 603 // Find which section this relocation belongs to, and get the 604 // relocation offset relative to the start of the section. 605 if (Sec32->VirtualAddress <= RelocAddress && 606 RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { 607 return RelocAddress - Sec32->VirtualAddress; 608 } 609 ++Sec32; 610 } 611 } 612 return InvalidRelocOffset; 613 } 614 615 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 616 uint32_t Index; 617 if (is64Bit()) { 618 const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 619 Index = Reloc->SymbolIndex; 620 621 if (Index >= getNumberOfSymbolTableEntries64()) 622 return symbol_end(); 623 } else { 624 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 625 Index = Reloc->SymbolIndex; 626 627 if (Index >= getLogicalNumberOfSymbolTableEntries32()) 628 return symbol_end(); 629 } 630 DataRefImpl SymDRI; 631 SymDRI.p = getSymbolEntryAddressByIndex(Index); 632 return symbol_iterator(SymbolRef(SymDRI, this)); 633 } 634 635 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 636 if (is64Bit()) 637 return viewAs<XCOFFRelocation64>(Rel.p)->Type; 638 return viewAs<XCOFFRelocation32>(Rel.p)->Type; 639 } 640 641 void XCOFFObjectFile::getRelocationTypeName( 642 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 643 StringRef Res; 644 if (is64Bit()) { 645 const XCOFFRelocation64 *Reloc = viewAs<XCOFFRelocation64>(Rel.p); 646 Res = XCOFF::getRelocationTypeString(Reloc->Type); 647 } else { 648 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 649 Res = XCOFF::getRelocationTypeString(Reloc->Type); 650 } 651 Result.append(Res.begin(), Res.end()); 652 } 653 654 Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 655 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); 656 uint32_t Result = SymbolRef::SF_None; 657 658 if (XCOFFSym.getSectionNumber() == XCOFF::N_ABS) 659 Result |= SymbolRef::SF_Absolute; 660 661 XCOFF::StorageClass SC = XCOFFSym.getStorageClass(); 662 if (XCOFF::C_EXT == SC || XCOFF::C_WEAKEXT == SC) 663 Result |= SymbolRef::SF_Global; 664 665 if (XCOFF::C_WEAKEXT == SC) 666 Result |= SymbolRef::SF_Weak; 667 668 if (XCOFFSym.isCsectSymbol()) { 669 Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = 670 XCOFFSym.getXCOFFCsectAuxRef(); 671 if (CsectAuxEntOrErr) { 672 if (CsectAuxEntOrErr.get().getSymbolType() == XCOFF::XTY_CM) 673 Result |= SymbolRef::SF_Common; 674 } else 675 return CsectAuxEntOrErr.takeError(); 676 } 677 678 if (XCOFFSym.getSectionNumber() == XCOFF::N_UNDEF) 679 Result |= SymbolRef::SF_Undefined; 680 681 // There is no visibility in old 32 bit XCOFF object file interpret. 682 if (is64Bit() || (auxiliaryHeader32() && (auxiliaryHeader32()->getVersion() == 683 NEW_XCOFF_INTERPRET))) { 684 uint16_t SymType = XCOFFSym.getSymbolType(); 685 if ((SymType & VISIBILITY_MASK) == SYM_V_HIDDEN) 686 Result |= SymbolRef::SF_Hidden; 687 688 if ((SymType & VISIBILITY_MASK) == SYM_V_EXPORTED) 689 Result |= SymbolRef::SF_Exported; 690 } 691 return Result; 692 } 693 694 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 695 DataRefImpl SymDRI; 696 SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); 697 return basic_symbol_iterator(SymbolRef(SymDRI, this)); 698 } 699 700 basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 701 DataRefImpl SymDRI; 702 const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries(); 703 SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries); 704 return basic_symbol_iterator(SymbolRef(SymDRI, this)); 705 } 706 707 XCOFFObjectFile::xcoff_symbol_iterator_range XCOFFObjectFile::symbols() const { 708 return xcoff_symbol_iterator_range(symbol_begin(), symbol_end()); 709 } 710 711 section_iterator XCOFFObjectFile::section_begin() const { 712 DataRefImpl DRI; 713 DRI.p = getSectionHeaderTableAddress(); 714 return section_iterator(SectionRef(DRI, this)); 715 } 716 717 section_iterator XCOFFObjectFile::section_end() const { 718 DataRefImpl DRI; 719 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 720 getNumberOfSections() * getSectionHeaderSize()); 721 return section_iterator(SectionRef(DRI, this)); 722 } 723 724 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } 725 726 StringRef XCOFFObjectFile::getFileFormatName() const { 727 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; 728 } 729 730 Triple::ArchType XCOFFObjectFile::getArch() const { 731 return is64Bit() ? Triple::ppc64 : Triple::ppc; 732 } 733 734 Expected<SubtargetFeatures> XCOFFObjectFile::getFeatures() const { 735 return SubtargetFeatures(); 736 } 737 738 bool XCOFFObjectFile::isRelocatableObject() const { 739 if (is64Bit()) 740 return !(fileHeader64()->Flags & NoRelMask); 741 return !(fileHeader32()->Flags & NoRelMask); 742 } 743 744 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 745 if (AuxiliaryHeader == nullptr) 746 return 0; 747 748 return is64Bit() ? auxiliaryHeader64()->getEntryPointAddr() 749 : auxiliaryHeader32()->getEntryPointAddr(); 750 } 751 752 StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const { 753 return StringSwitch<StringRef>(Name) 754 .Case("dwinfo", "debug_info") 755 .Case("dwline", "debug_line") 756 .Case("dwpbnms", "debug_pubnames") 757 .Case("dwpbtyp", "debug_pubtypes") 758 .Case("dwarnge", "debug_aranges") 759 .Case("dwabrev", "debug_abbrev") 760 .Case("dwstr", "debug_str") 761 .Case("dwrnges", "debug_ranges") 762 .Case("dwloc", "debug_loc") 763 .Case("dwframe", "debug_frame") 764 .Case("dwmac", "debug_macinfo") 765 .Default(Name); 766 } 767 768 size_t XCOFFObjectFile::getFileHeaderSize() const { 769 return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); 770 } 771 772 size_t XCOFFObjectFile::getSectionHeaderSize() const { 773 return is64Bit() ? sizeof(XCOFFSectionHeader64) : 774 sizeof(XCOFFSectionHeader32); 775 } 776 777 bool XCOFFObjectFile::is64Bit() const { 778 return Binary::ID_XCOFF64 == getType(); 779 } 780 781 Expected<StringRef> XCOFFObjectFile::getRawData(const char *Start, 782 uint64_t Size, 783 StringRef Name) const { 784 uintptr_t StartPtr = reinterpret_cast<uintptr_t>(Start); 785 // TODO: this path is untested. 786 if (Error E = Binary::checkOffset(Data, StartPtr, Size)) 787 return createError(toString(std::move(E)) + ": " + Name.data() + 788 " data with offset 0x" + Twine::utohexstr(StartPtr) + 789 " and size 0x" + Twine::utohexstr(Size) + 790 " goes past the end of the file"); 791 return StringRef(Start, Size); 792 } 793 794 uint16_t XCOFFObjectFile::getMagic() const { 795 return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; 796 } 797 798 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { 799 if (Num <= 0 || Num > getNumberOfSections()) 800 return createStringError(object_error::invalid_section_index, 801 "the section index (" + Twine(Num) + 802 ") is invalid"); 803 804 DataRefImpl DRI; 805 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 806 getSectionHeaderSize() * (Num - 1)); 807 return DRI; 808 } 809 810 DataRefImpl 811 XCOFFObjectFile::getSectionByType(XCOFF::SectionTypeFlags SectType) const { 812 DataRefImpl DRI; 813 auto GetSectionAddr = [&](const auto &Sections) -> uintptr_t { 814 for (const auto &Sec : Sections) 815 if (Sec.getSectionType() == SectType) 816 return reinterpret_cast<uintptr_t>(&Sec); 817 return uintptr_t(0); 818 }; 819 if (is64Bit()) 820 DRI.p = GetSectionAddr(sections64()); 821 else 822 DRI.p = GetSectionAddr(sections32()); 823 return DRI; 824 } 825 826 Expected<StringRef> 827 XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { 828 const int16_t SectionNum = SymEntPtr.getSectionNumber(); 829 830 switch (SectionNum) { 831 case XCOFF::N_DEBUG: 832 return "N_DEBUG"; 833 case XCOFF::N_ABS: 834 return "N_ABS"; 835 case XCOFF::N_UNDEF: 836 return "N_UNDEF"; 837 default: 838 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 839 if (SecRef) 840 return generateXCOFFFixedNameStringRef( 841 getSectionNameInternal(SecRef.get())); 842 return SecRef.takeError(); 843 } 844 } 845 846 unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 847 XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); 848 return XCOFFSymRef.getSectionNumber(); 849 } 850 851 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 852 return (SectionNumber <= 0 && SectionNumber >= -2); 853 } 854 855 uint16_t XCOFFObjectFile::getNumberOfSections() const { 856 return is64Bit() ? fileHeader64()->NumberOfSections 857 : fileHeader32()->NumberOfSections; 858 } 859 860 int32_t XCOFFObjectFile::getTimeStamp() const { 861 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 862 } 863 864 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 865 return is64Bit() ? fileHeader64()->AuxHeaderSize 866 : fileHeader32()->AuxHeaderSize; 867 } 868 869 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 870 return fileHeader32()->SymbolTableOffset; 871 } 872 873 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 874 // As far as symbol table size is concerned, if this field is negative it is 875 // to be treated as a 0. However since this field is also used for printing we 876 // don't want to truncate any negative values. 877 return fileHeader32()->NumberOfSymTableEntries; 878 } 879 880 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 881 return (fileHeader32()->NumberOfSymTableEntries >= 0 882 ? fileHeader32()->NumberOfSymTableEntries 883 : 0); 884 } 885 886 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 887 return fileHeader64()->SymbolTableOffset; 888 } 889 890 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 891 return fileHeader64()->NumberOfSymTableEntries; 892 } 893 894 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 895 return is64Bit() ? getNumberOfSymbolTableEntries64() 896 : getLogicalNumberOfSymbolTableEntries32(); 897 } 898 899 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 900 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 901 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 902 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 903 } 904 905 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 906 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 907 report_fatal_error("Symbol table entry is outside of symbol table."); 908 909 if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 910 report_fatal_error("Symbol table entry is outside of symbol table."); 911 912 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 913 reinterpret_cast<const char *>(SymbolTblPtr); 914 915 if (Offset % XCOFF::SymbolTableEntrySize != 0) 916 report_fatal_error( 917 "Symbol table entry position is not valid inside of symbol table."); 918 } 919 920 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 921 return (reinterpret_cast<const char *>(SymbolEntPtr) - 922 reinterpret_cast<const char *>(SymbolTblPtr)) / 923 XCOFF::SymbolTableEntrySize; 924 } 925 926 uint64_t XCOFFObjectFile::getSymbolSize(DataRefImpl Symb) const { 927 uint64_t Result = 0; 928 XCOFFSymbolRef XCOFFSym = toSymbolRef(Symb); 929 if (XCOFFSym.isCsectSymbol()) { 930 Expected<XCOFFCsectAuxRef> CsectAuxRefOrError = 931 XCOFFSym.getXCOFFCsectAuxRef(); 932 if (!CsectAuxRefOrError) 933 // TODO: report the error up the stack. 934 consumeError(CsectAuxRefOrError.takeError()); 935 else { 936 XCOFFCsectAuxRef CsectAuxRef = CsectAuxRefOrError.get(); 937 uint8_t SymType = CsectAuxRef.getSymbolType(); 938 if (SymType == XCOFF::XTY_SD || SymType == XCOFF::XTY_CM) 939 Result = CsectAuxRef.getSectionOrLength(); 940 } 941 } 942 return Result; 943 } 944 945 uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { 946 return getAdvancedSymbolEntryAddress( 947 reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); 948 } 949 950 Expected<StringRef> 951 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { 952 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 953 954 if (Index >= NumberOfSymTableEntries) 955 return createError("symbol index " + Twine(Index) + 956 " exceeds symbol count " + 957 Twine(NumberOfSymTableEntries)); 958 959 DataRefImpl SymDRI; 960 SymDRI.p = getSymbolEntryAddressByIndex(Index); 961 return getSymbolName(SymDRI); 962 } 963 964 uint16_t XCOFFObjectFile::getFlags() const { 965 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 966 } 967 968 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 969 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 970 } 971 972 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 973 return reinterpret_cast<uintptr_t>(SectionHeaderTable); 974 } 975 976 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 977 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 978 } 979 980 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 981 : ObjectFile(Type, Object) { 982 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 983 } 984 985 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 986 assert(is64Bit() && "64-bit interface called for non 64-bit file."); 987 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 988 return ArrayRef<XCOFFSectionHeader64>(TablePtr, 989 TablePtr + getNumberOfSections()); 990 } 991 992 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 993 assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 994 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 995 return ArrayRef<XCOFFSectionHeader32>(TablePtr, 996 TablePtr + getNumberOfSections()); 997 } 998 999 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO 1000 // section header contains the actual count of relocation entries in the s_paddr 1001 // field. STYP_OVRFLO headers contain the section index of their corresponding 1002 // sections as their raw "NumberOfRelocations" field value. 1003 template <typename T> 1004 Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries( 1005 const XCOFFSectionHeader<T> &Sec) const { 1006 const T &Section = static_cast<const T &>(Sec); 1007 if (is64Bit()) 1008 return Section.NumberOfRelocations; 1009 1010 uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1; 1011 if (Section.NumberOfRelocations < XCOFF::RelocOverflow) 1012 return Section.NumberOfRelocations; 1013 for (const auto &Sec : sections32()) { 1014 if (Sec.Flags == XCOFF::STYP_OVRFLO && 1015 Sec.NumberOfRelocations == SectionIndex) 1016 return Sec.PhysicalAddress; 1017 } 1018 return errorCodeToError(object_error::parse_failed); 1019 } 1020 1021 template <typename Shdr, typename Reloc> 1022 Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { 1023 uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), 1024 Sec.FileOffsetToRelocationInfo); 1025 auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec); 1026 if (Error E = NumRelocEntriesOrErr.takeError()) 1027 return std::move(E); 1028 1029 uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); 1030 static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 || 1031 sizeof(Reloc) == XCOFF::RelocationSerializationSize32), 1032 "Relocation structure is incorrect"); 1033 auto RelocationOrErr = 1034 getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr), 1035 NumRelocEntries * sizeof(Reloc)); 1036 if (!RelocationOrErr) 1037 return createError( 1038 toString(RelocationOrErr.takeError()) + ": relocations with offset 0x" + 1039 Twine::utohexstr(Sec.FileOffsetToRelocationInfo) + " and size 0x" + 1040 Twine::utohexstr(NumRelocEntries * sizeof(Reloc)) + 1041 " go past the end of the file"); 1042 1043 const Reloc *StartReloc = RelocationOrErr.get(); 1044 1045 return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); 1046 } 1047 1048 template <typename ExceptEnt> 1049 Expected<ArrayRef<ExceptEnt>> XCOFFObjectFile::getExceptionEntries() const { 1050 assert((is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry64)) || 1051 (!is64Bit() && sizeof(ExceptEnt) == sizeof(ExceptionSectionEntry32))); 1052 1053 Expected<uintptr_t> ExceptionSectOrErr = 1054 getSectionFileOffsetToRawData(XCOFF::STYP_EXCEPT); 1055 if (!ExceptionSectOrErr) 1056 return ExceptionSectOrErr.takeError(); 1057 1058 DataRefImpl DRI = getSectionByType(XCOFF::STYP_EXCEPT); 1059 if (DRI.p == 0) 1060 return ArrayRef<ExceptEnt>(); 1061 1062 ExceptEnt *ExceptEntStart = 1063 reinterpret_cast<ExceptEnt *>(*ExceptionSectOrErr); 1064 return ArrayRef<ExceptEnt>( 1065 ExceptEntStart, ExceptEntStart + getSectionSize(DRI) / sizeof(ExceptEnt)); 1066 } 1067 1068 template LLVM_EXPORT_TEMPLATE Expected<ArrayRef<ExceptionSectionEntry32>> 1069 XCOFFObjectFile::getExceptionEntries() const; 1070 template LLVM_EXPORT_TEMPLATE Expected<ArrayRef<ExceptionSectionEntry64>> 1071 XCOFFObjectFile::getExceptionEntries() const; 1072 1073 Expected<XCOFFStringTable> 1074 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 1075 // If there is a string table, then the buffer must contain at least 4 bytes 1076 // for the string table's size. Not having a string table is not an error. 1077 if (Error E = Binary::checkOffset( 1078 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { 1079 consumeError(std::move(E)); 1080 return XCOFFStringTable{0, nullptr}; 1081 } 1082 1083 // Read the size out of the buffer. 1084 uint32_t Size = support::endian::read32be(Obj->base() + Offset); 1085 1086 // If the size is less then 4, then the string table is just a size and no 1087 // string data. 1088 if (Size <= 4) 1089 return XCOFFStringTable{4, nullptr}; 1090 1091 auto StringTableOrErr = 1092 getObject<char>(Obj->Data, Obj->base() + Offset, Size); 1093 if (!StringTableOrErr) 1094 return createError(toString(StringTableOrErr.takeError()) + 1095 ": string table with offset 0x" + 1096 Twine::utohexstr(Offset) + " and size 0x" + 1097 Twine::utohexstr(Size) + 1098 " goes past the end of the file"); 1099 1100 const char *StringTablePtr = StringTableOrErr.get(); 1101 if (StringTablePtr[Size - 1] != '\0') 1102 return errorCodeToError(object_error::string_table_non_null_end); 1103 1104 return XCOFFStringTable{Size, StringTablePtr}; 1105 } 1106 1107 // This function returns the import file table. Each entry in the import file 1108 // table consists of: "path_name\0base_name\0archive_member_name\0". 1109 Expected<StringRef> XCOFFObjectFile::getImportFileTable() const { 1110 Expected<uintptr_t> LoaderSectionAddrOrError = 1111 getSectionFileOffsetToRawData(XCOFF::STYP_LOADER); 1112 if (!LoaderSectionAddrOrError) 1113 return LoaderSectionAddrOrError.takeError(); 1114 1115 uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); 1116 if (!LoaderSectionAddr) 1117 return StringRef(); 1118 1119 uint64_t OffsetToImportFileTable = 0; 1120 uint64_t LengthOfImportFileTable = 0; 1121 if (is64Bit()) { 1122 const LoaderSectionHeader64 *LoaderSec64 = 1123 viewAs<LoaderSectionHeader64>(LoaderSectionAddr); 1124 OffsetToImportFileTable = LoaderSec64->OffsetToImpid; 1125 LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl; 1126 } else { 1127 const LoaderSectionHeader32 *LoaderSec32 = 1128 viewAs<LoaderSectionHeader32>(LoaderSectionAddr); 1129 OffsetToImportFileTable = LoaderSec32->OffsetToImpid; 1130 LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl; 1131 } 1132 1133 auto ImportTableOrErr = getObject<char>( 1134 Data, 1135 reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable), 1136 LengthOfImportFileTable); 1137 if (!ImportTableOrErr) 1138 return createError( 1139 toString(ImportTableOrErr.takeError()) + 1140 ": import file table with offset 0x" + 1141 Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) + 1142 " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) + 1143 " goes past the end of the file"); 1144 1145 const char *ImportTablePtr = ImportTableOrErr.get(); 1146 if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0') 1147 return createError( 1148 ": import file name table with offset 0x" + 1149 Twine::utohexstr(LoaderSectionAddr + OffsetToImportFileTable) + 1150 " and size 0x" + Twine::utohexstr(LengthOfImportFileTable) + 1151 " must end with a null terminator"); 1152 1153 return StringRef(ImportTablePtr, LengthOfImportFileTable); 1154 } 1155 1156 Expected<std::unique_ptr<XCOFFObjectFile>> 1157 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 1158 // Can't use std::make_unique because of the private constructor. 1159 std::unique_ptr<XCOFFObjectFile> Obj; 1160 Obj.reset(new XCOFFObjectFile(Type, MBR)); 1161 1162 uint64_t CurOffset = 0; 1163 const auto *Base = Obj->base(); 1164 MemoryBufferRef Data = Obj->Data; 1165 1166 // Parse file header. 1167 auto FileHeaderOrErr = 1168 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 1169 if (Error E = FileHeaderOrErr.takeError()) 1170 return std::move(E); 1171 Obj->FileHeader = FileHeaderOrErr.get(); 1172 1173 CurOffset += Obj->getFileHeaderSize(); 1174 1175 if (Obj->getOptionalHeaderSize()) { 1176 auto AuxiliaryHeaderOrErr = 1177 getObject<void>(Data, Base + CurOffset, Obj->getOptionalHeaderSize()); 1178 if (Error E = AuxiliaryHeaderOrErr.takeError()) 1179 return std::move(E); 1180 Obj->AuxiliaryHeader = AuxiliaryHeaderOrErr.get(); 1181 } 1182 1183 CurOffset += Obj->getOptionalHeaderSize(); 1184 1185 // Parse the section header table if it is present. 1186 if (Obj->getNumberOfSections()) { 1187 uint64_t SectionHeadersSize = 1188 Obj->getNumberOfSections() * Obj->getSectionHeaderSize(); 1189 auto SecHeadersOrErr = 1190 getObject<void>(Data, Base + CurOffset, SectionHeadersSize); 1191 if (!SecHeadersOrErr) 1192 return createError(toString(SecHeadersOrErr.takeError()) + 1193 ": section headers with offset 0x" + 1194 Twine::utohexstr(CurOffset) + " and size 0x" + 1195 Twine::utohexstr(SectionHeadersSize) + 1196 " go past the end of the file"); 1197 1198 Obj->SectionHeaderTable = SecHeadersOrErr.get(); 1199 } 1200 1201 const uint32_t NumberOfSymbolTableEntries = 1202 Obj->getNumberOfSymbolTableEntries(); 1203 1204 // If there is no symbol table we are done parsing the memory buffer. 1205 if (NumberOfSymbolTableEntries == 0) 1206 return std::move(Obj); 1207 1208 // Parse symbol table. 1209 CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() 1210 : Obj->getSymbolTableOffset32(); 1211 const uint64_t SymbolTableSize = 1212 static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * 1213 NumberOfSymbolTableEntries; 1214 auto SymTableOrErr = 1215 getObject<void *>(Data, Base + CurOffset, SymbolTableSize); 1216 if (!SymTableOrErr) 1217 return createError( 1218 toString(SymTableOrErr.takeError()) + ": symbol table with offset 0x" + 1219 Twine::utohexstr(CurOffset) + " and size 0x" + 1220 Twine::utohexstr(SymbolTableSize) + " goes past the end of the file"); 1221 1222 Obj->SymbolTblPtr = SymTableOrErr.get(); 1223 CurOffset += SymbolTableSize; 1224 1225 // Parse String table. 1226 Expected<XCOFFStringTable> StringTableOrErr = 1227 parseStringTable(Obj.get(), CurOffset); 1228 if (Error E = StringTableOrErr.takeError()) 1229 return std::move(E); 1230 Obj->StringTable = StringTableOrErr.get(); 1231 1232 return std::move(Obj); 1233 } 1234 1235 Expected<std::unique_ptr<ObjectFile>> 1236 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 1237 unsigned FileType) { 1238 return XCOFFObjectFile::create(FileType, MemBufRef); 1239 } 1240 1241 std::optional<StringRef> XCOFFObjectFile::tryGetCPUName() const { 1242 return StringRef("future"); 1243 } 1244 1245 Expected<bool> XCOFFSymbolRef::isFunction() const { 1246 if (!isCsectSymbol()) 1247 return false; 1248 1249 if (getSymbolType() & FunctionSym) 1250 return true; 1251 1252 Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); 1253 if (!ExpCsectAuxEnt) 1254 return ExpCsectAuxEnt.takeError(); 1255 1256 const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); 1257 1258 if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR && 1259 CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_GL) 1260 return false; 1261 1262 // A function definition should not be a common type symbol or an external 1263 // symbol. 1264 if (CsectAuxRef.getSymbolType() == XCOFF::XTY_CM || 1265 CsectAuxRef.getSymbolType() == XCOFF::XTY_ER) 1266 return false; 1267 1268 // If the next symbol is an XTY_LD type symbol with the same address, this 1269 // XTY_SD symbol is not a function. Otherwise this is a function symbol for 1270 // -ffunction-sections. 1271 if (CsectAuxRef.getSymbolType() == XCOFF::XTY_SD) { 1272 // If this is a csect with size 0, it won't be a function definition. 1273 // This is used to work around the fact that LLVM always generates below 1274 // symbol for -ffunction-sections: 1275 // m 0x00000000 .text 1 unamex **No Symbol** 1276 // a4 0x00000000 0 0 SD PR 0 0 1277 // FIXME: remove or replace this meaningless symbol. 1278 if (getSize() == 0) 1279 return false; 1280 1281 xcoff_symbol_iterator NextIt(this); 1282 // If this is the last main symbol table entry, there won't be an XTY_LD 1283 // type symbol below. 1284 if (++NextIt == getObject()->symbol_end()) 1285 return true; 1286 1287 if (cantFail(getAddress()) != cantFail(NextIt->getAddress())) 1288 return true; 1289 1290 // Check next symbol is XTY_LD. If so, this symbol is not a function. 1291 Expected<XCOFFCsectAuxRef> NextCsectAuxEnt = NextIt->getXCOFFCsectAuxRef(); 1292 if (!NextCsectAuxEnt) 1293 return NextCsectAuxEnt.takeError(); 1294 1295 if (NextCsectAuxEnt.get().getSymbolType() == XCOFF::XTY_LD) 1296 return false; 1297 1298 return true; 1299 } 1300 1301 if (CsectAuxRef.getSymbolType() == XCOFF::XTY_LD) 1302 return true; 1303 1304 return createError( 1305 "symbol csect aux entry with index " + 1306 Twine(getObject()->getSymbolIndex(CsectAuxRef.getEntryAddress())) + 1307 " has invalid symbol type " + 1308 Twine::utohexstr(CsectAuxRef.getSymbolType())); 1309 } 1310 1311 bool XCOFFSymbolRef::isCsectSymbol() const { 1312 XCOFF::StorageClass SC = getStorageClass(); 1313 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 1314 SC == XCOFF::C_HIDEXT); 1315 } 1316 1317 Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { 1318 assert(isCsectSymbol() && 1319 "Calling csect symbol interface with a non-csect symbol."); 1320 1321 uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); 1322 1323 Expected<StringRef> NameOrErr = getName(); 1324 if (auto Err = NameOrErr.takeError()) 1325 return std::move(Err); 1326 1327 uint32_t SymbolIdx = getObject()->getSymbolIndex(getEntryAddress()); 1328 if (!NumberOfAuxEntries) { 1329 return createError("csect symbol \"" + *NameOrErr + "\" with index " + 1330 Twine(SymbolIdx) + " contains no auxiliary entry"); 1331 } 1332 1333 if (!getObject()->is64Bit()) { 1334 // In XCOFF32, the csect auxilliary entry is always the last auxiliary 1335 // entry for the symbol. 1336 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 1337 getEntryAddress(), NumberOfAuxEntries); 1338 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); 1339 } 1340 1341 // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. 1342 // We need to iterate through all the auxiliary entries to find it. 1343 for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { 1344 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 1345 getEntryAddress(), Index); 1346 if (*getObject()->getSymbolAuxType(AuxAddr) == 1347 XCOFF::SymbolAuxType::AUX_CSECT) { 1348 #ifndef NDEBUG 1349 getObject()->checkSymbolEntryPointer(AuxAddr); 1350 #endif 1351 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); 1352 } 1353 } 1354 1355 return createError( 1356 "a csect auxiliary entry has not been found for symbol \"" + *NameOrErr + 1357 "\" with index " + Twine(SymbolIdx)); 1358 } 1359 1360 Expected<StringRef> XCOFFSymbolRef::getName() const { 1361 // A storage class value with the high-order bit on indicates that the name is 1362 // a symbolic debugger stabstring. 1363 if (getStorageClass() & 0x80) 1364 return StringRef("Unimplemented Debug Name"); 1365 1366 if (!getObject()->is64Bit()) { 1367 if (getSymbol32()->NameInStrTbl.Magic != 1368 XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 1369 return generateXCOFFFixedNameStringRef(getSymbol32()->SymbolName); 1370 1371 return getObject()->getStringTableEntry(getSymbol32()->NameInStrTbl.Offset); 1372 } 1373 1374 return getObject()->getStringTableEntry(getSymbol64()->Offset); 1375 } 1376 1377 // Explicitly instantiate template classes. 1378 template struct LLVM_EXPORT_TEMPLATE XCOFFSectionHeader<XCOFFSectionHeader32>; 1379 template struct LLVM_EXPORT_TEMPLATE XCOFFSectionHeader<XCOFFSectionHeader64>; 1380 1381 template struct LLVM_EXPORT_TEMPLATE XCOFFRelocation<llvm::support::ubig32_t>; 1382 template struct LLVM_EXPORT_TEMPLATE XCOFFRelocation<llvm::support::ubig64_t>; 1383 1384 template LLVM_EXPORT_TEMPLATE 1385 llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>> 1386 llvm::object::XCOFFObjectFile::relocations< 1387 llvm::object::XCOFFSectionHeader64, llvm::object::XCOFFRelocation64>( 1388 llvm::object::XCOFFSectionHeader64 const &) const; 1389 template LLVM_EXPORT_TEMPLATE 1390 llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>> 1391 llvm::object::XCOFFObjectFile::relocations< 1392 llvm::object::XCOFFSectionHeader32, llvm::object::XCOFFRelocation32>( 1393 llvm::object::XCOFFSectionHeader32 const &) const; 1394 1395 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { 1396 if (Bytes.size() < 4) 1397 return false; 1398 1399 return support::endian::read32be(Bytes.data()) == 0; 1400 } 1401 1402 #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) 1403 #define GETVALUEWITHMASKSHIFT(X, S) \ 1404 ((Data & (TracebackTable::X)) >> (TracebackTable::S)) 1405 1406 Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) { 1407 Error Err = Error::success(); 1408 TBVectorExt TBTVecExt(TBvectorStrRef, Err); 1409 if (Err) 1410 return std::move(Err); 1411 return TBTVecExt; 1412 } 1413 1414 TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { 1415 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); 1416 Data = support::endian::read16be(Ptr); 1417 uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); 1418 unsigned ParmsNum = 1419 GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); 1420 1421 ErrorAsOutParameter EAO(Err); 1422 Expected<SmallString<32>> VecParmsTypeOrError = 1423 parseVectorParmsType(VecParmsTypeValue, ParmsNum); 1424 if (!VecParmsTypeOrError) 1425 Err = VecParmsTypeOrError.takeError(); 1426 else 1427 VecParmsInfo = VecParmsTypeOrError.get(); 1428 } 1429 1430 uint8_t TBVectorExt::getNumberOfVRSaved() const { 1431 return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); 1432 } 1433 1434 bool TBVectorExt::isVRSavedOnStack() const { 1435 return GETVALUEWITHMASK(IsVRSavedOnStackMask); 1436 } 1437 1438 bool TBVectorExt::hasVarArgs() const { 1439 return GETVALUEWITHMASK(HasVarArgsMask); 1440 } 1441 1442 uint8_t TBVectorExt::getNumberOfVectorParms() const { 1443 return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, 1444 NumberOfVectorParmsShift); 1445 } 1446 1447 bool TBVectorExt::hasVMXInstruction() const { 1448 return GETVALUEWITHMASK(HasVMXInstructionMask); 1449 } 1450 #undef GETVALUEWITHMASK 1451 #undef GETVALUEWITHMASKSHIFT 1452 1453 Expected<XCOFFTracebackTable> 1454 XCOFFTracebackTable::create(const uint8_t *Ptr, uint64_t &Size, bool Is64Bit) { 1455 Error Err = Error::success(); 1456 XCOFFTracebackTable TBT(Ptr, Size, Err, Is64Bit); 1457 if (Err) 1458 return std::move(Err); 1459 return TBT; 1460 } 1461 1462 XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, 1463 Error &Err, bool Is64Bit) 1464 : TBPtr(Ptr), Is64BitObj(Is64Bit) { 1465 ErrorAsOutParameter EAO(Err); 1466 DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, 1467 /*AddressSize=*/0); 1468 DataExtractor::Cursor Cur(/*Offset=*/0); 1469 1470 // Skip 8 bytes of mandatory fields. 1471 DE.getU64(Cur); 1472 1473 unsigned FixedParmsNum = getNumberOfFixedParms(); 1474 unsigned FloatingParmsNum = getNumberOfFPParms(); 1475 uint32_t ParamsTypeValue = 0; 1476 1477 // Begin to parse optional fields. 1478 if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) 1479 ParamsTypeValue = DE.getU32(Cur); 1480 1481 if (Cur && hasTraceBackTableOffset()) 1482 TraceBackTableOffset = DE.getU32(Cur); 1483 1484 if (Cur && isInterruptHandler()) 1485 HandlerMask = DE.getU32(Cur); 1486 1487 if (Cur && hasControlledStorage()) { 1488 NumOfCtlAnchors = DE.getU32(Cur); 1489 if (Cur && NumOfCtlAnchors) { 1490 SmallVector<uint32_t, 8> Disp; 1491 Disp.reserve(*NumOfCtlAnchors); 1492 for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) 1493 Disp.push_back(DE.getU32(Cur)); 1494 if (Cur) 1495 ControlledStorageInfoDisp = std::move(Disp); 1496 } 1497 } 1498 1499 if (Cur && isFuncNamePresent()) { 1500 uint16_t FunctionNameLen = DE.getU16(Cur); 1501 if (Cur) 1502 FunctionName = DE.getBytes(Cur, FunctionNameLen); 1503 } 1504 1505 if (Cur && isAllocaUsed()) 1506 AllocaRegister = DE.getU8(Cur); 1507 1508 unsigned VectorParmsNum = 0; 1509 if (Cur && hasVectorInfo()) { 1510 StringRef VectorExtRef = DE.getBytes(Cur, 6); 1511 if (Cur) { 1512 Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef); 1513 if (!TBVecExtOrErr) { 1514 Err = TBVecExtOrErr.takeError(); 1515 return; 1516 } 1517 VecExt = TBVecExtOrErr.get(); 1518 VectorParmsNum = VecExt->getNumberOfVectorParms(); 1519 // Skip two bytes of padding after vector info. 1520 DE.skip(Cur, 2); 1521 } 1522 } 1523 1524 // As long as there is no fixed-point or floating-point parameter, this 1525 // field remains not present even when hasVectorInfo gives true and 1526 // indicates the presence of vector parameters. 1527 if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { 1528 Expected<SmallString<32>> ParmsTypeOrError = 1529 hasVectorInfo() 1530 ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, 1531 FloatingParmsNum, VectorParmsNum) 1532 : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); 1533 1534 if (!ParmsTypeOrError) { 1535 Err = ParmsTypeOrError.takeError(); 1536 return; 1537 } 1538 ParmsType = ParmsTypeOrError.get(); 1539 } 1540 1541 if (Cur && hasExtensionTable()) { 1542 ExtensionTable = DE.getU8(Cur); 1543 1544 if (*ExtensionTable & ExtendedTBTableFlag::TB_EH_INFO) { 1545 // eh_info displacement must be 4-byte aligned. 1546 Cur.seek(alignTo(Cur.tell(), 4)); 1547 EhInfoDisp = Is64BitObj ? DE.getU64(Cur) : DE.getU32(Cur); 1548 } 1549 } 1550 if (!Cur) 1551 Err = Cur.takeError(); 1552 1553 Size = Cur.tell(); 1554 } 1555 1556 #define GETBITWITHMASK(P, X) \ 1557 (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) 1558 #define GETBITWITHMASKSHIFT(P, X, S) \ 1559 ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ 1560 (TracebackTable::S)) 1561 1562 uint8_t XCOFFTracebackTable::getVersion() const { 1563 return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); 1564 } 1565 1566 uint8_t XCOFFTracebackTable::getLanguageID() const { 1567 return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); 1568 } 1569 1570 bool XCOFFTracebackTable::isGlobalLinkage() const { 1571 return GETBITWITHMASK(0, IsGlobaLinkageMask); 1572 } 1573 1574 bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { 1575 return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); 1576 } 1577 1578 bool XCOFFTracebackTable::hasTraceBackTableOffset() const { 1579 return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); 1580 } 1581 1582 bool XCOFFTracebackTable::isInternalProcedure() const { 1583 return GETBITWITHMASK(0, IsInternalProcedureMask); 1584 } 1585 1586 bool XCOFFTracebackTable::hasControlledStorage() const { 1587 return GETBITWITHMASK(0, HasControlledStorageMask); 1588 } 1589 1590 bool XCOFFTracebackTable::isTOCless() const { 1591 return GETBITWITHMASK(0, IsTOClessMask); 1592 } 1593 1594 bool XCOFFTracebackTable::isFloatingPointPresent() const { 1595 return GETBITWITHMASK(0, IsFloatingPointPresentMask); 1596 } 1597 1598 bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { 1599 return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); 1600 } 1601 1602 bool XCOFFTracebackTable::isInterruptHandler() const { 1603 return GETBITWITHMASK(0, IsInterruptHandlerMask); 1604 } 1605 1606 bool XCOFFTracebackTable::isFuncNamePresent() const { 1607 return GETBITWITHMASK(0, IsFunctionNamePresentMask); 1608 } 1609 1610 bool XCOFFTracebackTable::isAllocaUsed() const { 1611 return GETBITWITHMASK(0, IsAllocaUsedMask); 1612 } 1613 1614 uint8_t XCOFFTracebackTable::getOnConditionDirective() const { 1615 return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, 1616 OnConditionDirectiveShift); 1617 } 1618 1619 bool XCOFFTracebackTable::isCRSaved() const { 1620 return GETBITWITHMASK(0, IsCRSavedMask); 1621 } 1622 1623 bool XCOFFTracebackTable::isLRSaved() const { 1624 return GETBITWITHMASK(0, IsLRSavedMask); 1625 } 1626 1627 bool XCOFFTracebackTable::isBackChainStored() const { 1628 return GETBITWITHMASK(4, IsBackChainStoredMask); 1629 } 1630 1631 bool XCOFFTracebackTable::isFixup() const { 1632 return GETBITWITHMASK(4, IsFixupMask); 1633 } 1634 1635 uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { 1636 return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); 1637 } 1638 1639 bool XCOFFTracebackTable::hasExtensionTable() const { 1640 return GETBITWITHMASK(4, HasExtensionTableMask); 1641 } 1642 1643 bool XCOFFTracebackTable::hasVectorInfo() const { 1644 return GETBITWITHMASK(4, HasVectorInfoMask); 1645 } 1646 1647 uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { 1648 return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); 1649 } 1650 1651 uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { 1652 return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, 1653 NumberOfFixedParmsShift); 1654 } 1655 1656 uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { 1657 return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, 1658 NumberOfFloatingPointParmsShift); 1659 } 1660 1661 bool XCOFFTracebackTable::hasParmsOnStack() const { 1662 return GETBITWITHMASK(4, HasParmsOnStackMask); 1663 } 1664 1665 #undef GETBITWITHMASK 1666 #undef GETBITWITHMASKSHIFT 1667 } // namespace object 1668 } // namespace llvm 1669