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/MC/SubtargetFeature.h" 16 #include "llvm/Support/DataExtractor.h" 17 #include <cstddef> 18 #include <cstring> 19 20 namespace llvm { 21 22 using namespace XCOFF; 23 24 namespace object { 25 26 static const uint8_t FunctionSym = 0x20; 27 static const uint16_t NoRelMask = 0x0001; 28 static const size_t SymbolAuxTypeOffset = 17; 29 30 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer 31 // 'M'. Returns a pointer to the underlying object on success. 32 template <typename T> 33 static Expected<const T *> getObject(MemoryBufferRef M, const void *Ptr, 34 const uint64_t Size = sizeof(T)) { 35 uintptr_t Addr = reinterpret_cast<uintptr_t>(Ptr); 36 if (Error E = Binary::checkOffset(M, Addr, Size)) 37 return std::move(E); 38 return reinterpret_cast<const T *>(Addr); 39 } 40 41 static uintptr_t getWithOffset(uintptr_t Base, ptrdiff_t Offset) { 42 return reinterpret_cast<uintptr_t>(reinterpret_cast<const char *>(Base) + 43 Offset); 44 } 45 46 template <typename T> static const T *viewAs(uintptr_t in) { 47 return reinterpret_cast<const T *>(in); 48 } 49 50 static StringRef generateXCOFFFixedNameStringRef(const char *Name) { 51 auto NulCharPtr = 52 static_cast<const char *>(memchr(Name, '\0', XCOFF::NameSize)); 53 return NulCharPtr ? StringRef(Name, NulCharPtr - Name) 54 : StringRef(Name, XCOFF::NameSize); 55 } 56 57 template <typename T> StringRef XCOFFSectionHeader<T>::getName() const { 58 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 59 return generateXCOFFFixedNameStringRef(DerivedXCOFFSectionHeader.Name); 60 } 61 62 template <typename T> uint16_t XCOFFSectionHeader<T>::getSectionType() const { 63 const T &DerivedXCOFFSectionHeader = static_cast<const T &>(*this); 64 return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask; 65 } 66 67 template <typename T> 68 bool XCOFFSectionHeader<T>::isReservedSectionType() const { 69 return getSectionType() & SectionFlagsReservedMask; 70 } 71 72 bool XCOFFRelocation32::isRelocationSigned() const { 73 return Info & XR_SIGN_INDICATOR_MASK; 74 } 75 76 bool XCOFFRelocation32::isFixupIndicated() const { 77 return Info & XR_FIXUP_INDICATOR_MASK; 78 } 79 80 uint8_t XCOFFRelocation32::getRelocatedLength() const { 81 // The relocation encodes the bit length being relocated minus 1. Add back 82 // the 1 to get the actual length being relocated. 83 return (Info & XR_BIASED_LENGTH_MASK) + 1; 84 } 85 86 uintptr_t 87 XCOFFObjectFile::getAdvancedSymbolEntryAddress(uintptr_t CurrentAddress, 88 uint32_t Distance) { 89 return getWithOffset(CurrentAddress, Distance * XCOFF::SymbolTableEntrySize); 90 } 91 92 const XCOFF::SymbolAuxType * 93 XCOFFObjectFile::getSymbolAuxType(uintptr_t AuxEntryAddress) const { 94 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 95 return viewAs<XCOFF::SymbolAuxType>( 96 getWithOffset(AuxEntryAddress, SymbolAuxTypeOffset)); 97 } 98 99 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr, 100 uintptr_t TableAddress) const { 101 if (Addr < TableAddress) 102 report_fatal_error("Section header outside of section header table."); 103 104 uintptr_t Offset = Addr - TableAddress; 105 if (Offset >= getSectionHeaderSize() * getNumberOfSections()) 106 report_fatal_error("Section header outside of section header table."); 107 108 if (Offset % getSectionHeaderSize() != 0) 109 report_fatal_error( 110 "Section header pointer does not point to a valid section header."); 111 } 112 113 const XCOFFSectionHeader32 * 114 XCOFFObjectFile::toSection32(DataRefImpl Ref) const { 115 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 116 #ifndef NDEBUG 117 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 118 #endif 119 return viewAs<XCOFFSectionHeader32>(Ref.p); 120 } 121 122 const XCOFFSectionHeader64 * 123 XCOFFObjectFile::toSection64(DataRefImpl Ref) const { 124 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 125 #ifndef NDEBUG 126 checkSectionAddress(Ref.p, getSectionHeaderTableAddress()); 127 #endif 128 return viewAs<XCOFFSectionHeader64>(Ref.p); 129 } 130 131 XCOFFSymbolRef XCOFFObjectFile::toSymbolRef(DataRefImpl Ref) const { 132 assert(Ref.p != 0 && "Symbol table pointer can not be nullptr!"); 133 #ifndef NDEBUG 134 checkSymbolEntryPointer(Ref.p); 135 #endif 136 return XCOFFSymbolRef(Ref, this); 137 } 138 139 const XCOFFFileHeader32 *XCOFFObjectFile::fileHeader32() const { 140 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 141 return static_cast<const XCOFFFileHeader32 *>(FileHeader); 142 } 143 144 const XCOFFFileHeader64 *XCOFFObjectFile::fileHeader64() const { 145 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 146 return static_cast<const XCOFFFileHeader64 *>(FileHeader); 147 } 148 149 const XCOFFSectionHeader32 * 150 XCOFFObjectFile::sectionHeaderTable32() const { 151 assert(!is64Bit() && "32-bit interface called on 64-bit object file."); 152 return static_cast<const XCOFFSectionHeader32 *>(SectionHeaderTable); 153 } 154 155 const XCOFFSectionHeader64 * 156 XCOFFObjectFile::sectionHeaderTable64() const { 157 assert(is64Bit() && "64-bit interface called on a 32-bit object file."); 158 return static_cast<const XCOFFSectionHeader64 *>(SectionHeaderTable); 159 } 160 161 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 162 uintptr_t NextSymbolAddr = getAdvancedSymbolEntryAddress( 163 Symb.p, toSymbolRef(Symb).getNumberOfAuxEntries() + 1); 164 #ifndef NDEBUG 165 // This function is used by basic_symbol_iterator, which allows to 166 // point to the end-of-symbol-table address. 167 if (NextSymbolAddr != getEndOfSymbolTableAddress()) 168 checkSymbolEntryPointer(NextSymbolAddr); 169 #endif 170 Symb.p = NextSymbolAddr; 171 } 172 173 Expected<StringRef> 174 XCOFFObjectFile::getStringTableEntry(uint32_t Offset) const { 175 // The byte offset is relative to the start of the string table. 176 // A byte offset value of 0 is a null or zero-length symbol 177 // name. A byte offset in the range 1 to 3 (inclusive) points into the length 178 // field; as a soft-error recovery mechanism, we treat such cases as having an 179 // offset of 0. 180 if (Offset < 4) 181 return StringRef(nullptr, 0); 182 183 if (StringTable.Data != nullptr && StringTable.Size > Offset) 184 return (StringTable.Data + Offset); 185 186 return make_error<GenericBinaryError>("Bad offset for string table entry", 187 object_error::parse_failed); 188 } 189 190 Expected<StringRef> 191 XCOFFObjectFile::getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const { 192 if (CFileEntPtr->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 193 return generateXCOFFFixedNameStringRef(CFileEntPtr->Name); 194 return getStringTableEntry(CFileEntPtr->NameInStrTbl.Offset); 195 } 196 197 Expected<StringRef> XCOFFObjectFile::getSymbolName(DataRefImpl Symb) const { 198 return toSymbolRef(Symb).getName(); 199 } 200 201 Expected<uint64_t> XCOFFObjectFile::getSymbolAddress(DataRefImpl Symb) const { 202 return toSymbolRef(Symb).getValue(); 203 } 204 205 uint64_t XCOFFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 206 return toSymbolRef(Symb).getValue(); 207 } 208 209 uint64_t XCOFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 210 uint64_t Result = 0; 211 llvm_unreachable("Not yet implemented!"); 212 return Result; 213 } 214 215 Expected<SymbolRef::Type> 216 XCOFFObjectFile::getSymbolType(DataRefImpl Symb) const { 217 // TODO: Return the correct symbol type. 218 return SymbolRef::ST_Other; 219 } 220 221 Expected<section_iterator> 222 XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { 223 const int16_t SectNum = toSymbolRef(Symb).getSectionNumber(); 224 225 if (isReservedSectionNumber(SectNum)) 226 return section_end(); 227 228 Expected<DataRefImpl> ExpSec = getSectionByNum(SectNum); 229 if (!ExpSec) 230 return ExpSec.takeError(); 231 232 return section_iterator(SectionRef(ExpSec.get(), this)); 233 } 234 235 void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { 236 const char *Ptr = reinterpret_cast<const char *>(Sec.p); 237 Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); 238 } 239 240 Expected<StringRef> XCOFFObjectFile::getSectionName(DataRefImpl Sec) const { 241 return generateXCOFFFixedNameStringRef(getSectionNameInternal(Sec)); 242 } 243 244 uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { 245 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 246 // with MSVC. 247 if (is64Bit()) 248 return toSection64(Sec)->VirtualAddress; 249 250 return toSection32(Sec)->VirtualAddress; 251 } 252 253 uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { 254 // Section numbers in XCOFF are numbered beginning at 1. A section number of 255 // zero is used to indicate that a symbol is being imported or is undefined. 256 if (is64Bit()) 257 return toSection64(Sec) - sectionHeaderTable64() + 1; 258 else 259 return toSection32(Sec) - sectionHeaderTable32() + 1; 260 } 261 262 uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { 263 // Avoid ternary due to failure to convert the ubig32_t value to a unit64_t 264 // with MSVC. 265 if (is64Bit()) 266 return toSection64(Sec)->SectionSize; 267 268 return toSection32(Sec)->SectionSize; 269 } 270 271 Expected<ArrayRef<uint8_t>> 272 XCOFFObjectFile::getSectionContents(DataRefImpl Sec) const { 273 if (isSectionVirtual(Sec)) 274 return ArrayRef<uint8_t>(); 275 276 uint64_t OffsetToRaw; 277 if (is64Bit()) 278 OffsetToRaw = toSection64(Sec)->FileOffsetToRawData; 279 else 280 OffsetToRaw = toSection32(Sec)->FileOffsetToRawData; 281 282 const uint8_t * ContentStart = base() + OffsetToRaw; 283 uint64_t SectionSize = getSectionSize(Sec); 284 if (checkOffset(Data, reinterpret_cast<uintptr_t>(ContentStart), SectionSize)) 285 return make_error<BinaryError>(); 286 287 return makeArrayRef(ContentStart,SectionSize); 288 } 289 290 uint64_t XCOFFObjectFile::getSectionAlignment(DataRefImpl Sec) const { 291 uint64_t Result = 0; 292 llvm_unreachable("Not yet implemented!"); 293 return Result; 294 } 295 296 bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { 297 return false; 298 } 299 300 bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { 301 return getSectionFlags(Sec) & XCOFF::STYP_TEXT; 302 } 303 304 bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { 305 uint32_t Flags = getSectionFlags(Sec); 306 return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); 307 } 308 309 bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { 310 uint32_t Flags = getSectionFlags(Sec); 311 return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); 312 } 313 314 bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { 315 return is64Bit() ? toSection64(Sec)->FileOffsetToRawData == 0 316 : toSection32(Sec)->FileOffsetToRawData == 0; 317 } 318 319 relocation_iterator XCOFFObjectFile::section_rel_begin(DataRefImpl Sec) const { 320 if (is64Bit()) 321 report_fatal_error("64-bit support not implemented yet"); 322 const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 323 auto RelocationsOrErr = relocations(*SectionEntPtr); 324 if (Error E = RelocationsOrErr.takeError()) 325 return relocation_iterator(RelocationRef()); 326 DataRefImpl Ret; 327 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().begin()); 328 return relocation_iterator(RelocationRef(Ret, this)); 329 } 330 331 relocation_iterator XCOFFObjectFile::section_rel_end(DataRefImpl Sec) const { 332 if (is64Bit()) 333 report_fatal_error("64-bit support not implemented yet"); 334 const XCOFFSectionHeader32 *SectionEntPtr = toSection32(Sec); 335 auto RelocationsOrErr = relocations(*SectionEntPtr); 336 if (Error E = RelocationsOrErr.takeError()) 337 return relocation_iterator(RelocationRef()); 338 DataRefImpl Ret; 339 Ret.p = reinterpret_cast<uintptr_t>(&*RelocationsOrErr.get().end()); 340 return relocation_iterator(RelocationRef(Ret, this)); 341 } 342 343 void XCOFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 344 Rel.p = reinterpret_cast<uintptr_t>(viewAs<XCOFFRelocation32>(Rel.p) + 1); 345 } 346 347 uint64_t XCOFFObjectFile::getRelocationOffset(DataRefImpl Rel) const { 348 if (is64Bit()) 349 report_fatal_error("64-bit support not implemented yet"); 350 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 351 const XCOFFSectionHeader32 *Sec32 = sectionHeaderTable32(); 352 const uint32_t RelocAddress = Reloc->VirtualAddress; 353 const uint16_t NumberOfSections = getNumberOfSections(); 354 for (uint16_t i = 0; i < NumberOfSections; ++i) { 355 // Find which section this relocation is belonging to, and get the 356 // relocation offset relative to the start of the section. 357 if (Sec32->VirtualAddress <= RelocAddress && 358 RelocAddress < Sec32->VirtualAddress + Sec32->SectionSize) { 359 return RelocAddress - Sec32->VirtualAddress; 360 } 361 ++Sec32; 362 } 363 return InvalidRelocOffset; 364 } 365 366 symbol_iterator XCOFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 367 if (is64Bit()) 368 report_fatal_error("64-bit support not implemented yet"); 369 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 370 const uint32_t Index = Reloc->SymbolIndex; 371 372 if (Index >= getLogicalNumberOfSymbolTableEntries32()) 373 return symbol_end(); 374 375 DataRefImpl SymDRI; 376 SymDRI.p = getSymbolEntryAddressByIndex(Index); 377 return symbol_iterator(SymbolRef(SymDRI, this)); 378 } 379 380 uint64_t XCOFFObjectFile::getRelocationType(DataRefImpl Rel) const { 381 if (is64Bit()) 382 report_fatal_error("64-bit support not implemented yet"); 383 return viewAs<XCOFFRelocation32>(Rel.p)->Type; 384 } 385 386 void XCOFFObjectFile::getRelocationTypeName( 387 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 388 if (is64Bit()) 389 report_fatal_error("64-bit support not implemented yet"); 390 const XCOFFRelocation32 *Reloc = viewAs<XCOFFRelocation32>(Rel.p); 391 StringRef Res = XCOFF::getRelocationTypeString(Reloc->Type); 392 Result.append(Res.begin(), Res.end()); 393 } 394 395 Expected<uint32_t> XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { 396 uint32_t Result = 0; 397 // TODO: Return correct symbol flags. 398 return Result; 399 } 400 401 basic_symbol_iterator XCOFFObjectFile::symbol_begin() const { 402 DataRefImpl SymDRI; 403 SymDRI.p = reinterpret_cast<uintptr_t>(SymbolTblPtr); 404 return basic_symbol_iterator(SymbolRef(SymDRI, this)); 405 } 406 407 basic_symbol_iterator XCOFFObjectFile::symbol_end() const { 408 DataRefImpl SymDRI; 409 const uint32_t NumberOfSymbolTableEntries = getNumberOfSymbolTableEntries(); 410 SymDRI.p = getSymbolEntryAddressByIndex(NumberOfSymbolTableEntries); 411 return basic_symbol_iterator(SymbolRef(SymDRI, this)); 412 } 413 414 section_iterator XCOFFObjectFile::section_begin() const { 415 DataRefImpl DRI; 416 DRI.p = getSectionHeaderTableAddress(); 417 return section_iterator(SectionRef(DRI, this)); 418 } 419 420 section_iterator XCOFFObjectFile::section_end() const { 421 DataRefImpl DRI; 422 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 423 getNumberOfSections() * getSectionHeaderSize()); 424 return section_iterator(SectionRef(DRI, this)); 425 } 426 427 uint8_t XCOFFObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } 428 429 StringRef XCOFFObjectFile::getFileFormatName() const { 430 return is64Bit() ? "aix5coff64-rs6000" : "aixcoff-rs6000"; 431 } 432 433 Triple::ArchType XCOFFObjectFile::getArch() const { 434 return is64Bit() ? Triple::ppc64 : Triple::ppc; 435 } 436 437 SubtargetFeatures XCOFFObjectFile::getFeatures() const { 438 return SubtargetFeatures(); 439 } 440 441 bool XCOFFObjectFile::isRelocatableObject() const { 442 if (is64Bit()) 443 return !(fileHeader64()->Flags & NoRelMask); 444 return !(fileHeader32()->Flags & NoRelMask); 445 } 446 447 Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { 448 // TODO FIXME Should get from auxiliary_header->o_entry when support for the 449 // auxiliary_header is added. 450 return 0; 451 } 452 453 StringRef XCOFFObjectFile::mapDebugSectionName(StringRef Name) const { 454 return StringSwitch<StringRef>(Name) 455 .Case("dwinfo", "debug_info") 456 .Case("dwline", "debug_line") 457 .Case("dwpbnms", "debug_pubnames") 458 .Case("dwpbtyp", "debug_pubtypes") 459 .Case("dwarnge", "debug_aranges") 460 .Case("dwabrev", "debug_abbrev") 461 .Case("dwstr", "debug_str") 462 .Case("dwrnges", "debug_ranges") 463 .Case("dwloc", "debug_loc") 464 .Case("dwframe", "debug_frame") 465 .Case("dwmac", "debug_macinfo") 466 .Default(Name); 467 } 468 469 size_t XCOFFObjectFile::getFileHeaderSize() const { 470 return is64Bit() ? sizeof(XCOFFFileHeader64) : sizeof(XCOFFFileHeader32); 471 } 472 473 size_t XCOFFObjectFile::getSectionHeaderSize() const { 474 return is64Bit() ? sizeof(XCOFFSectionHeader64) : 475 sizeof(XCOFFSectionHeader32); 476 } 477 478 bool XCOFFObjectFile::is64Bit() const { 479 return Binary::ID_XCOFF64 == getType(); 480 } 481 482 uint16_t XCOFFObjectFile::getMagic() const { 483 return is64Bit() ? fileHeader64()->Magic : fileHeader32()->Magic; 484 } 485 486 Expected<DataRefImpl> XCOFFObjectFile::getSectionByNum(int16_t Num) const { 487 if (Num <= 0 || Num > getNumberOfSections()) 488 return errorCodeToError(object_error::invalid_section_index); 489 490 DataRefImpl DRI; 491 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 492 getSectionHeaderSize() * (Num - 1)); 493 return DRI; 494 } 495 496 Expected<StringRef> 497 XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { 498 const int16_t SectionNum = SymEntPtr.getSectionNumber(); 499 500 switch (SectionNum) { 501 case XCOFF::N_DEBUG: 502 return "N_DEBUG"; 503 case XCOFF::N_ABS: 504 return "N_ABS"; 505 case XCOFF::N_UNDEF: 506 return "N_UNDEF"; 507 default: 508 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 509 if (SecRef) 510 return generateXCOFFFixedNameStringRef( 511 getSectionNameInternal(SecRef.get())); 512 return SecRef.takeError(); 513 } 514 } 515 516 unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 517 XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); 518 return XCOFFSymRef.getSectionNumber(); 519 } 520 521 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 522 return (SectionNumber <= 0 && SectionNumber >= -2); 523 } 524 525 uint16_t XCOFFObjectFile::getNumberOfSections() const { 526 return is64Bit() ? fileHeader64()->NumberOfSections 527 : fileHeader32()->NumberOfSections; 528 } 529 530 int32_t XCOFFObjectFile::getTimeStamp() const { 531 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 532 } 533 534 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 535 return is64Bit() ? fileHeader64()->AuxHeaderSize 536 : fileHeader32()->AuxHeaderSize; 537 } 538 539 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 540 return fileHeader32()->SymbolTableOffset; 541 } 542 543 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 544 // As far as symbol table size is concerned, if this field is negative it is 545 // to be treated as a 0. However since this field is also used for printing we 546 // don't want to truncate any negative values. 547 return fileHeader32()->NumberOfSymTableEntries; 548 } 549 550 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 551 return (fileHeader32()->NumberOfSymTableEntries >= 0 552 ? fileHeader32()->NumberOfSymTableEntries 553 : 0); 554 } 555 556 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 557 return fileHeader64()->SymbolTableOffset; 558 } 559 560 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 561 return fileHeader64()->NumberOfSymTableEntries; 562 } 563 564 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 565 return is64Bit() ? getNumberOfSymbolTableEntries64() 566 : getLogicalNumberOfSymbolTableEntries32(); 567 } 568 569 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 570 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 571 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 572 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 573 } 574 575 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 576 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 577 report_fatal_error("Symbol table entry is outside of symbol table."); 578 579 if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 580 report_fatal_error("Symbol table entry is outside of symbol table."); 581 582 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 583 reinterpret_cast<const char *>(SymbolTblPtr); 584 585 if (Offset % XCOFF::SymbolTableEntrySize != 0) 586 report_fatal_error( 587 "Symbol table entry position is not valid inside of symbol table."); 588 } 589 590 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 591 return (reinterpret_cast<const char *>(SymbolEntPtr) - 592 reinterpret_cast<const char *>(SymbolTblPtr)) / 593 XCOFF::SymbolTableEntrySize; 594 } 595 596 uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { 597 return getAdvancedSymbolEntryAddress( 598 reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); 599 } 600 601 Expected<StringRef> 602 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { 603 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 604 605 if (Index >= NumberOfSymTableEntries) 606 return errorCodeToError(object_error::invalid_symbol_index); 607 608 DataRefImpl SymDRI; 609 SymDRI.p = getSymbolEntryAddressByIndex(Index); 610 return getSymbolName(SymDRI); 611 } 612 613 uint16_t XCOFFObjectFile::getFlags() const { 614 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 615 } 616 617 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 618 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 619 } 620 621 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 622 return reinterpret_cast<uintptr_t>(SectionHeaderTable); 623 } 624 625 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 626 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 627 } 628 629 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 630 : ObjectFile(Type, Object) { 631 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 632 } 633 634 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 635 assert(is64Bit() && "64-bit interface called for non 64-bit file."); 636 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 637 return ArrayRef<XCOFFSectionHeader64>(TablePtr, 638 TablePtr + getNumberOfSections()); 639 } 640 641 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 642 assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 643 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 644 return ArrayRef<XCOFFSectionHeader32>(TablePtr, 645 TablePtr + getNumberOfSections()); 646 } 647 648 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO 649 // section header contains the actual count of relocation entries in the s_paddr 650 // field. STYP_OVRFLO headers contain the section index of their corresponding 651 // sections as their raw "NumberOfRelocations" field value. 652 Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries( 653 const XCOFFSectionHeader32 &Sec) const { 654 655 uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1; 656 657 if (Sec.NumberOfRelocations < XCOFF::RelocOverflow) 658 return Sec.NumberOfRelocations; 659 for (const auto &Sec : sections32()) { 660 if (Sec.Flags == XCOFF::STYP_OVRFLO && 661 Sec.NumberOfRelocations == SectionIndex) 662 return Sec.PhysicalAddress; 663 } 664 return errorCodeToError(object_error::parse_failed); 665 } 666 667 Expected<ArrayRef<XCOFFRelocation32>> 668 XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const { 669 uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), 670 Sec.FileOffsetToRelocationInfo); 671 auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec); 672 if (Error E = NumRelocEntriesOrErr.takeError()) 673 return std::move(E); 674 675 uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); 676 677 static_assert( 678 sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, ""); 679 auto RelocationOrErr = 680 getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr), 681 NumRelocEntries * sizeof(XCOFFRelocation32)); 682 if (Error E = RelocationOrErr.takeError()) 683 return std::move(E); 684 685 const XCOFFRelocation32 *StartReloc = RelocationOrErr.get(); 686 687 return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries); 688 } 689 690 Expected<XCOFFStringTable> 691 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 692 // If there is a string table, then the buffer must contain at least 4 bytes 693 // for the string table's size. Not having a string table is not an error. 694 if (Error E = Binary::checkOffset( 695 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { 696 consumeError(std::move(E)); 697 return XCOFFStringTable{0, nullptr}; 698 } 699 700 // Read the size out of the buffer. 701 uint32_t Size = support::endian::read32be(Obj->base() + Offset); 702 703 // If the size is less then 4, then the string table is just a size and no 704 // string data. 705 if (Size <= 4) 706 return XCOFFStringTable{4, nullptr}; 707 708 auto StringTableOrErr = 709 getObject<char>(Obj->Data, Obj->base() + Offset, Size); 710 if (Error E = StringTableOrErr.takeError()) 711 return std::move(E); 712 713 const char *StringTablePtr = StringTableOrErr.get(); 714 if (StringTablePtr[Size - 1] != '\0') 715 return errorCodeToError(object_error::string_table_non_null_end); 716 717 return XCOFFStringTable{Size, StringTablePtr}; 718 } 719 720 Expected<std::unique_ptr<XCOFFObjectFile>> 721 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 722 // Can't use std::make_unique because of the private constructor. 723 std::unique_ptr<XCOFFObjectFile> Obj; 724 Obj.reset(new XCOFFObjectFile(Type, MBR)); 725 726 uint64_t CurOffset = 0; 727 const auto *Base = Obj->base(); 728 MemoryBufferRef Data = Obj->Data; 729 730 // Parse file header. 731 auto FileHeaderOrErr = 732 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 733 if (Error E = FileHeaderOrErr.takeError()) 734 return std::move(E); 735 Obj->FileHeader = FileHeaderOrErr.get(); 736 737 CurOffset += Obj->getFileHeaderSize(); 738 // TODO FIXME we don't have support for an optional header yet, so just skip 739 // past it. 740 CurOffset += Obj->getOptionalHeaderSize(); 741 742 // Parse the section header table if it is present. 743 if (Obj->getNumberOfSections()) { 744 auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 745 Obj->getNumberOfSections() * 746 Obj->getSectionHeaderSize()); 747 if (Error E = SecHeadersOrErr.takeError()) 748 return std::move(E); 749 Obj->SectionHeaderTable = SecHeadersOrErr.get(); 750 } 751 752 const uint32_t NumberOfSymbolTableEntries = 753 Obj->getNumberOfSymbolTableEntries(); 754 755 // If there is no symbol table we are done parsing the memory buffer. 756 if (NumberOfSymbolTableEntries == 0) 757 return std::move(Obj); 758 759 // Parse symbol table. 760 CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() 761 : Obj->getSymbolTableOffset32(); 762 const uint64_t SymbolTableSize = 763 static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * 764 NumberOfSymbolTableEntries; 765 auto SymTableOrErr = 766 getObject<void *>(Data, Base + CurOffset, SymbolTableSize); 767 if (Error E = SymTableOrErr.takeError()) 768 return std::move(E); 769 Obj->SymbolTblPtr = SymTableOrErr.get(); 770 CurOffset += SymbolTableSize; 771 772 // Parse String table. 773 Expected<XCOFFStringTable> StringTableOrErr = 774 parseStringTable(Obj.get(), CurOffset); 775 if (Error E = StringTableOrErr.takeError()) 776 return std::move(E); 777 Obj->StringTable = StringTableOrErr.get(); 778 779 return std::move(Obj); 780 } 781 782 Expected<std::unique_ptr<ObjectFile>> 783 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 784 unsigned FileType) { 785 return XCOFFObjectFile::create(FileType, MemBufRef); 786 } 787 788 bool XCOFFSymbolRef::isFunction() const { 789 if (!isCsectSymbol()) 790 return false; 791 792 if (getSymbolType() & FunctionSym) 793 return true; 794 795 Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); 796 if (!ExpCsectAuxEnt) 797 return false; 798 799 const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); 800 801 // A function definition should be a label definition. 802 // FIXME: This is not necessarily the case when -ffunction-sections is 803 // enabled. 804 if (!CsectAuxRef.isLabel()) 805 return false; 806 807 if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) 808 return false; 809 810 const int16_t SectNum = getSectionNumber(); 811 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); 812 if (!SI) { 813 // If we could not get the section, then this symbol should not be 814 // a function. So consume the error and return `false` to move on. 815 consumeError(SI.takeError()); 816 return false; 817 } 818 819 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); 820 } 821 822 bool XCOFFSymbolRef::isCsectSymbol() const { 823 XCOFF::StorageClass SC = getStorageClass(); 824 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 825 SC == XCOFF::C_HIDEXT); 826 } 827 828 Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { 829 assert(isCsectSymbol() && 830 "Calling csect symbol interface with a non-csect symbol."); 831 832 uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); 833 834 Expected<StringRef> NameOrErr = getName(); 835 if (auto Err = NameOrErr.takeError()) 836 return std::move(Err); 837 838 if (!NumberOfAuxEntries) { 839 return createStringError(object_error::parse_failed, 840 "csect symbol \"" + *NameOrErr + 841 "\" contains no auxiliary entry"); 842 } 843 844 if (!OwningObjectPtr->is64Bit()) { 845 // In XCOFF32, the csect auxilliary entry is always the last auxiliary 846 // entry for the symbol. 847 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 848 getEntryAddress(), NumberOfAuxEntries); 849 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); 850 } 851 852 // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. 853 // We need to iterate through all the auxiliary entries to find it. 854 for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { 855 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 856 getEntryAddress(), Index); 857 if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == 858 XCOFF::SymbolAuxType::AUX_CSECT) { 859 #ifndef NDEBUG 860 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); 861 #endif 862 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); 863 } 864 } 865 866 return createStringError( 867 object_error::parse_failed, 868 "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); 869 } 870 871 Expected<StringRef> XCOFFSymbolRef::getName() const { 872 // A storage class value with the high-order bit on indicates that the name is 873 // a symbolic debugger stabstring. 874 if (getStorageClass() & 0x80) 875 return StringRef("Unimplemented Debug Name"); 876 877 if (Entry32) { 878 if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 879 return generateXCOFFFixedNameStringRef(Entry32->SymbolName); 880 881 return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); 882 } 883 884 return OwningObjectPtr->getStringTableEntry(Entry64->Offset); 885 } 886 887 // Explictly instantiate template classes. 888 template struct XCOFFSectionHeader<XCOFFSectionHeader32>; 889 template struct XCOFFSectionHeader<XCOFFSectionHeader64>; 890 891 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { 892 if (Bytes.size() < 4) 893 return false; 894 895 return support::endian::read32be(Bytes.data()) == 0; 896 } 897 898 TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) { 899 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); 900 Data = support::endian::read16be(Ptr); 901 VecParmsInfo = support::endian::read32be(Ptr + 2); 902 } 903 904 #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) 905 #define GETVALUEWITHMASKSHIFT(X, S) \ 906 ((Data & (TracebackTable::X)) >> (TracebackTable::S)) 907 uint8_t TBVectorExt::getNumberOfVRSaved() const { 908 return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); 909 } 910 911 bool TBVectorExt::isVRSavedOnStack() const { 912 return GETVALUEWITHMASK(IsVRSavedOnStackMask); 913 } 914 915 bool TBVectorExt::hasVarArgs() const { 916 return GETVALUEWITHMASK(HasVarArgsMask); 917 } 918 uint8_t TBVectorExt::getNumberOfVectorParms() const { 919 return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, 920 NumberOfVectorParmsShift); 921 } 922 923 bool TBVectorExt::hasVMXInstruction() const { 924 return GETVALUEWITHMASK(HasVMXInstructionMask); 925 } 926 #undef GETVALUEWITHMASK 927 #undef GETVALUEWITHMASKSHIFT 928 929 SmallString<32> TBVectorExt::getVectorParmsInfoString() const { 930 SmallString<32> ParmsType; 931 uint32_t Value = VecParmsInfo; 932 for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) { 933 if (I != 0) 934 ParmsType += ", "; 935 switch (Value & TracebackTable::ParmTypeMask) { 936 case TracebackTable::ParmTypeIsVectorCharBit: 937 ParmsType += "vc"; 938 break; 939 940 case TracebackTable::ParmTypeIsVectorShortBit: 941 ParmsType += "vs"; 942 break; 943 944 case TracebackTable::ParmTypeIsVectorIntBit: 945 ParmsType += "vi"; 946 break; 947 948 case TracebackTable::ParmTypeIsVectorFloatBit: 949 ParmsType += "vf"; 950 break; 951 } 952 Value <<= 2; 953 } 954 return ParmsType; 955 } 956 957 static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value, 958 unsigned int ParmsNum) { 959 SmallString<32> ParmsType; 960 unsigned I = 0; 961 bool Begin = false; 962 while (I < ParmsNum || Value) { 963 if (Begin) 964 ParmsType += ", "; 965 else 966 Begin = true; 967 968 switch (Value & TracebackTable::ParmTypeMask) { 969 case TracebackTable::ParmTypeIsFixedBits: 970 ParmsType += "i"; 971 ++I; 972 break; 973 case TracebackTable::ParmTypeIsVectorBits: 974 ParmsType += "v"; 975 break; 976 case TracebackTable::ParmTypeIsFloatingBits: 977 ParmsType += "f"; 978 ++I; 979 break; 980 case TracebackTable::ParmTypeIsDoubleBits: 981 ParmsType += "d"; 982 ++I; 983 break; 984 default: 985 assert(false && "Unrecognized bits in ParmsType."); 986 } 987 Value <<= 2; 988 } 989 assert(I == ParmsNum && 990 "The total parameters number of fixed-point or floating-point " 991 "parameters not equal to the number in the parameter type!"); 992 return ParmsType; 993 } 994 995 Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, 996 uint64_t &Size) { 997 Error Err = Error::success(); 998 XCOFFTracebackTable TBT(Ptr, Size, Err); 999 if (Err) 1000 return std::move(Err); 1001 return TBT; 1002 } 1003 1004 XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, 1005 Error &Err) 1006 : TBPtr(Ptr) { 1007 ErrorAsOutParameter EAO(&Err); 1008 DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, 1009 /*AddressSize=*/0); 1010 DataExtractor::Cursor Cur(/*Offset=*/0); 1011 1012 // Skip 8 bytes of mandatory fields. 1013 DE.getU64(Cur); 1014 1015 // Begin to parse optional fields. 1016 if (Cur) { 1017 unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms(); 1018 1019 // As long as there are no "fixed-point" or floating-point parameters, this 1020 // field remains not present even when hasVectorInfo gives true and 1021 // indicates the presence of vector parameters. 1022 if (ParmNum > 0) { 1023 uint32_t ParamsTypeValue = DE.getU32(Cur); 1024 if (Cur) 1025 ParmsType = hasVectorInfo() 1026 ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum) 1027 : parseParmsType(ParamsTypeValue, ParmNum); 1028 } 1029 } 1030 1031 if (Cur && hasTraceBackTableOffset()) 1032 TraceBackTableOffset = DE.getU32(Cur); 1033 1034 if (Cur && isInterruptHandler()) 1035 HandlerMask = DE.getU32(Cur); 1036 1037 if (Cur && hasControlledStorage()) { 1038 NumOfCtlAnchors = DE.getU32(Cur); 1039 if (Cur && NumOfCtlAnchors) { 1040 SmallVector<uint32_t, 8> Disp; 1041 Disp.reserve(NumOfCtlAnchors.getValue()); 1042 for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) 1043 Disp.push_back(DE.getU32(Cur)); 1044 if (Cur) 1045 ControlledStorageInfoDisp = std::move(Disp); 1046 } 1047 } 1048 1049 if (Cur && isFuncNamePresent()) { 1050 uint16_t FunctionNameLen = DE.getU16(Cur); 1051 if (Cur) 1052 FunctionName = DE.getBytes(Cur, FunctionNameLen); 1053 } 1054 1055 if (Cur && isAllocaUsed()) 1056 AllocaRegister = DE.getU8(Cur); 1057 1058 if (Cur && hasVectorInfo()) { 1059 StringRef VectorExtRef = DE.getBytes(Cur, 6); 1060 if (Cur) 1061 VecExt = TBVectorExt(VectorExtRef); 1062 } 1063 1064 if (Cur && hasExtensionTable()) 1065 ExtensionTable = DE.getU8(Cur); 1066 1067 if (!Cur) 1068 Err = Cur.takeError(); 1069 Size = Cur.tell(); 1070 } 1071 1072 #define GETBITWITHMASK(P, X) \ 1073 (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) 1074 #define GETBITWITHMASKSHIFT(P, X, S) \ 1075 ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ 1076 (TracebackTable::S)) 1077 1078 uint8_t XCOFFTracebackTable::getVersion() const { 1079 return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); 1080 } 1081 1082 uint8_t XCOFFTracebackTable::getLanguageID() const { 1083 return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); 1084 } 1085 1086 bool XCOFFTracebackTable::isGlobalLinkage() const { 1087 return GETBITWITHMASK(0, IsGlobaLinkageMask); 1088 } 1089 1090 bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { 1091 return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); 1092 } 1093 1094 bool XCOFFTracebackTable::hasTraceBackTableOffset() const { 1095 return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); 1096 } 1097 1098 bool XCOFFTracebackTable::isInternalProcedure() const { 1099 return GETBITWITHMASK(0, IsInternalProcedureMask); 1100 } 1101 1102 bool XCOFFTracebackTable::hasControlledStorage() const { 1103 return GETBITWITHMASK(0, HasControlledStorageMask); 1104 } 1105 1106 bool XCOFFTracebackTable::isTOCless() const { 1107 return GETBITWITHMASK(0, IsTOClessMask); 1108 } 1109 1110 bool XCOFFTracebackTable::isFloatingPointPresent() const { 1111 return GETBITWITHMASK(0, IsFloatingPointPresentMask); 1112 } 1113 1114 bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { 1115 return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); 1116 } 1117 1118 bool XCOFFTracebackTable::isInterruptHandler() const { 1119 return GETBITWITHMASK(0, IsInterruptHandlerMask); 1120 } 1121 1122 bool XCOFFTracebackTable::isFuncNamePresent() const { 1123 return GETBITWITHMASK(0, IsFunctionNamePresentMask); 1124 } 1125 1126 bool XCOFFTracebackTable::isAllocaUsed() const { 1127 return GETBITWITHMASK(0, IsAllocaUsedMask); 1128 } 1129 1130 uint8_t XCOFFTracebackTable::getOnConditionDirective() const { 1131 return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, 1132 OnConditionDirectiveShift); 1133 } 1134 1135 bool XCOFFTracebackTable::isCRSaved() const { 1136 return GETBITWITHMASK(0, IsCRSavedMask); 1137 } 1138 1139 bool XCOFFTracebackTable::isLRSaved() const { 1140 return GETBITWITHMASK(0, IsLRSavedMask); 1141 } 1142 1143 bool XCOFFTracebackTable::isBackChainStored() const { 1144 return GETBITWITHMASK(4, IsBackChainStoredMask); 1145 } 1146 1147 bool XCOFFTracebackTable::isFixup() const { 1148 return GETBITWITHMASK(4, IsFixupMask); 1149 } 1150 1151 uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { 1152 return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); 1153 } 1154 1155 bool XCOFFTracebackTable::hasExtensionTable() const { 1156 return GETBITWITHMASK(4, HasExtensionTableMask); 1157 } 1158 1159 bool XCOFFTracebackTable::hasVectorInfo() const { 1160 return GETBITWITHMASK(4, HasVectorInfoMask); 1161 } 1162 1163 uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { 1164 return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); 1165 } 1166 1167 uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { 1168 return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, 1169 NumberOfFixedParmsShift); 1170 } 1171 1172 uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { 1173 return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, 1174 NumberOfFloatingPointParmsShift); 1175 } 1176 1177 bool XCOFFTracebackTable::hasParmsOnStack() const { 1178 return GETBITWITHMASK(4, HasParmsOnStackMask); 1179 } 1180 1181 #undef GETBITWITHMASK 1182 #undef GETBITWITHMASKSHIFT 1183 } // namespace object 1184 } // namespace llvm 1185