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 llvm_unreachable("Not yet implemented!"); 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 llvm_unreachable("Not yet implemented!"); 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 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 517 return (SectionNumber <= 0 && SectionNumber >= -2); 518 } 519 520 uint16_t XCOFFObjectFile::getNumberOfSections() const { 521 return is64Bit() ? fileHeader64()->NumberOfSections 522 : fileHeader32()->NumberOfSections; 523 } 524 525 int32_t XCOFFObjectFile::getTimeStamp() const { 526 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 527 } 528 529 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 530 return is64Bit() ? fileHeader64()->AuxHeaderSize 531 : fileHeader32()->AuxHeaderSize; 532 } 533 534 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 535 return fileHeader32()->SymbolTableOffset; 536 } 537 538 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 539 // As far as symbol table size is concerned, if this field is negative it is 540 // to be treated as a 0. However since this field is also used for printing we 541 // don't want to truncate any negative values. 542 return fileHeader32()->NumberOfSymTableEntries; 543 } 544 545 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 546 return (fileHeader32()->NumberOfSymTableEntries >= 0 547 ? fileHeader32()->NumberOfSymTableEntries 548 : 0); 549 } 550 551 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 552 return fileHeader64()->SymbolTableOffset; 553 } 554 555 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 556 return fileHeader64()->NumberOfSymTableEntries; 557 } 558 559 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 560 return is64Bit() ? getNumberOfSymbolTableEntries64() 561 : getLogicalNumberOfSymbolTableEntries32(); 562 } 563 564 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 565 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 566 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 567 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 568 } 569 570 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 571 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 572 report_fatal_error("Symbol table entry is outside of symbol table."); 573 574 if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 575 report_fatal_error("Symbol table entry is outside of symbol table."); 576 577 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 578 reinterpret_cast<const char *>(SymbolTblPtr); 579 580 if (Offset % XCOFF::SymbolTableEntrySize != 0) 581 report_fatal_error( 582 "Symbol table entry position is not valid inside of symbol table."); 583 } 584 585 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 586 return (reinterpret_cast<const char *>(SymbolEntPtr) - 587 reinterpret_cast<const char *>(SymbolTblPtr)) / 588 XCOFF::SymbolTableEntrySize; 589 } 590 591 uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { 592 return getAdvancedSymbolEntryAddress( 593 reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); 594 } 595 596 Expected<StringRef> 597 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { 598 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 599 600 if (Index >= NumberOfSymTableEntries) 601 return errorCodeToError(object_error::invalid_symbol_index); 602 603 DataRefImpl SymDRI; 604 SymDRI.p = getSymbolEntryAddressByIndex(Index); 605 return getSymbolName(SymDRI); 606 } 607 608 uint16_t XCOFFObjectFile::getFlags() const { 609 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 610 } 611 612 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 613 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 614 } 615 616 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 617 return reinterpret_cast<uintptr_t>(SectionHeaderTable); 618 } 619 620 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 621 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 622 } 623 624 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 625 : ObjectFile(Type, Object) { 626 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 627 } 628 629 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 630 assert(is64Bit() && "64-bit interface called for non 64-bit file."); 631 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 632 return ArrayRef<XCOFFSectionHeader64>(TablePtr, 633 TablePtr + getNumberOfSections()); 634 } 635 636 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 637 assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 638 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 639 return ArrayRef<XCOFFSectionHeader32>(TablePtr, 640 TablePtr + getNumberOfSections()); 641 } 642 643 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO 644 // section header contains the actual count of relocation entries in the s_paddr 645 // field. STYP_OVRFLO headers contain the section index of their corresponding 646 // sections as their raw "NumberOfRelocations" field value. 647 Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries( 648 const XCOFFSectionHeader32 &Sec) const { 649 650 uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1; 651 652 if (Sec.NumberOfRelocations < XCOFF::RelocOverflow) 653 return Sec.NumberOfRelocations; 654 for (const auto &Sec : sections32()) { 655 if (Sec.Flags == XCOFF::STYP_OVRFLO && 656 Sec.NumberOfRelocations == SectionIndex) 657 return Sec.PhysicalAddress; 658 } 659 return errorCodeToError(object_error::parse_failed); 660 } 661 662 Expected<ArrayRef<XCOFFRelocation32>> 663 XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const { 664 uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), 665 Sec.FileOffsetToRelocationInfo); 666 auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec); 667 if (Error E = NumRelocEntriesOrErr.takeError()) 668 return std::move(E); 669 670 uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); 671 672 static_assert( 673 sizeof(XCOFFRelocation32) == XCOFF::RelocationSerializationSize32, ""); 674 auto RelocationOrErr = 675 getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr), 676 NumRelocEntries * sizeof(XCOFFRelocation32)); 677 if (Error E = RelocationOrErr.takeError()) 678 return std::move(E); 679 680 const XCOFFRelocation32 *StartReloc = RelocationOrErr.get(); 681 682 return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries); 683 } 684 685 Expected<XCOFFStringTable> 686 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 687 // If there is a string table, then the buffer must contain at least 4 bytes 688 // for the string table's size. Not having a string table is not an error. 689 if (Error E = Binary::checkOffset( 690 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { 691 consumeError(std::move(E)); 692 return XCOFFStringTable{0, nullptr}; 693 } 694 695 // Read the size out of the buffer. 696 uint32_t Size = support::endian::read32be(Obj->base() + Offset); 697 698 // If the size is less then 4, then the string table is just a size and no 699 // string data. 700 if (Size <= 4) 701 return XCOFFStringTable{4, nullptr}; 702 703 auto StringTableOrErr = 704 getObject<char>(Obj->Data, Obj->base() + Offset, Size); 705 if (Error E = StringTableOrErr.takeError()) 706 return std::move(E); 707 708 const char *StringTablePtr = StringTableOrErr.get(); 709 if (StringTablePtr[Size - 1] != '\0') 710 return errorCodeToError(object_error::string_table_non_null_end); 711 712 return XCOFFStringTable{Size, StringTablePtr}; 713 } 714 715 Expected<std::unique_ptr<XCOFFObjectFile>> 716 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 717 // Can't use std::make_unique because of the private constructor. 718 std::unique_ptr<XCOFFObjectFile> Obj; 719 Obj.reset(new XCOFFObjectFile(Type, MBR)); 720 721 uint64_t CurOffset = 0; 722 const auto *Base = Obj->base(); 723 MemoryBufferRef Data = Obj->Data; 724 725 // Parse file header. 726 auto FileHeaderOrErr = 727 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 728 if (Error E = FileHeaderOrErr.takeError()) 729 return std::move(E); 730 Obj->FileHeader = FileHeaderOrErr.get(); 731 732 CurOffset += Obj->getFileHeaderSize(); 733 // TODO FIXME we don't have support for an optional header yet, so just skip 734 // past it. 735 CurOffset += Obj->getOptionalHeaderSize(); 736 737 // Parse the section header table if it is present. 738 if (Obj->getNumberOfSections()) { 739 auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 740 Obj->getNumberOfSections() * 741 Obj->getSectionHeaderSize()); 742 if (Error E = SecHeadersOrErr.takeError()) 743 return std::move(E); 744 Obj->SectionHeaderTable = SecHeadersOrErr.get(); 745 } 746 747 const uint32_t NumberOfSymbolTableEntries = 748 Obj->getNumberOfSymbolTableEntries(); 749 750 // If there is no symbol table we are done parsing the memory buffer. 751 if (NumberOfSymbolTableEntries == 0) 752 return std::move(Obj); 753 754 // Parse symbol table. 755 CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() 756 : Obj->getSymbolTableOffset32(); 757 const uint64_t SymbolTableSize = 758 static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * 759 NumberOfSymbolTableEntries; 760 auto SymTableOrErr = 761 getObject<void *>(Data, Base + CurOffset, SymbolTableSize); 762 if (Error E = SymTableOrErr.takeError()) 763 return std::move(E); 764 Obj->SymbolTblPtr = SymTableOrErr.get(); 765 CurOffset += SymbolTableSize; 766 767 // Parse String table. 768 Expected<XCOFFStringTable> StringTableOrErr = 769 parseStringTable(Obj.get(), CurOffset); 770 if (Error E = StringTableOrErr.takeError()) 771 return std::move(E); 772 Obj->StringTable = StringTableOrErr.get(); 773 774 return std::move(Obj); 775 } 776 777 Expected<std::unique_ptr<ObjectFile>> 778 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 779 unsigned FileType) { 780 return XCOFFObjectFile::create(FileType, MemBufRef); 781 } 782 783 bool XCOFFSymbolRef::isFunction() const { 784 if (!isCsectSymbol()) 785 return false; 786 787 if (getSymbolType() & FunctionSym) 788 return true; 789 790 Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); 791 if (!ExpCsectAuxEnt) 792 return false; 793 794 const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); 795 796 // A function definition should be a label definition. 797 // FIXME: This is not necessarily the case when -ffunction-sections is 798 // enabled. 799 if (!CsectAuxRef.isLabel()) 800 return false; 801 802 if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) 803 return false; 804 805 const int16_t SectNum = getSectionNumber(); 806 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); 807 if (!SI) { 808 // If we could not get the section, then this symbol should not be 809 // a function. So consume the error and return `false` to move on. 810 consumeError(SI.takeError()); 811 return false; 812 } 813 814 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); 815 } 816 817 bool XCOFFSymbolRef::isCsectSymbol() const { 818 XCOFF::StorageClass SC = getStorageClass(); 819 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 820 SC == XCOFF::C_HIDEXT); 821 } 822 823 Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { 824 assert(isCsectSymbol() && 825 "Calling csect symbol interface with a non-csect symbol."); 826 827 uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); 828 829 Expected<StringRef> NameOrErr = getName(); 830 if (auto Err = NameOrErr.takeError()) 831 return std::move(Err); 832 833 if (!NumberOfAuxEntries) { 834 return createStringError(object_error::parse_failed, 835 "csect symbol \"" + *NameOrErr + 836 "\" contains no auxiliary entry"); 837 } 838 839 if (!OwningObjectPtr->is64Bit()) { 840 // In XCOFF32, the csect auxilliary entry is always the last auxiliary 841 // entry for the symbol. 842 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 843 getEntryAddress(), NumberOfAuxEntries); 844 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); 845 } 846 847 // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. 848 // We need to iterate through all the auxiliary entries to find it. 849 for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { 850 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 851 getEntryAddress(), Index); 852 if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == 853 XCOFF::SymbolAuxType::AUX_CSECT) { 854 #ifndef NDEBUG 855 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); 856 #endif 857 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); 858 } 859 } 860 861 return createStringError( 862 object_error::parse_failed, 863 "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); 864 } 865 866 Expected<StringRef> XCOFFSymbolRef::getName() const { 867 // A storage class value with the high-order bit on indicates that the name is 868 // a symbolic debugger stabstring. 869 if (getStorageClass() & 0x80) 870 return StringRef("Unimplemented Debug Name"); 871 872 if (Entry32) { 873 if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 874 return generateXCOFFFixedNameStringRef(Entry32->SymbolName); 875 876 return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); 877 } 878 879 return OwningObjectPtr->getStringTableEntry(Entry64->Offset); 880 } 881 882 // Explictly instantiate template classes. 883 template struct XCOFFSectionHeader<XCOFFSectionHeader32>; 884 template struct XCOFFSectionHeader<XCOFFSectionHeader64>; 885 886 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { 887 if (Bytes.size() < 4) 888 return false; 889 890 return support::endian::read32be(Bytes.data()) == 0; 891 } 892 893 TBVectorExt::TBVectorExt(StringRef TBvectorStrRef) { 894 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); 895 Data = support::endian::read16be(Ptr); 896 VecParmsInfo = support::endian::read32be(Ptr + 2); 897 } 898 899 #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) 900 #define GETVALUEWITHMASKSHIFT(X, S) \ 901 ((Data & (TracebackTable::X)) >> (TracebackTable::S)) 902 uint8_t TBVectorExt::getNumberOfVRSaved() const { 903 return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); 904 } 905 906 bool TBVectorExt::isVRSavedOnStack() const { 907 return GETVALUEWITHMASK(IsVRSavedOnStackMask); 908 } 909 910 bool TBVectorExt::hasVarArgs() const { 911 return GETVALUEWITHMASK(HasVarArgsMask); 912 } 913 uint8_t TBVectorExt::getNumberOfVectorParms() const { 914 return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, 915 NumberOfVectorParmsShift); 916 } 917 918 bool TBVectorExt::hasVMXInstruction() const { 919 return GETVALUEWITHMASK(HasVMXInstructionMask); 920 } 921 #undef GETVALUEWITHMASK 922 #undef GETVALUEWITHMASKSHIFT 923 924 SmallString<32> TBVectorExt::getVectorParmsInfoString() const { 925 SmallString<32> ParmsType; 926 uint32_t Value = VecParmsInfo; 927 for (uint8_t I = 0; I < getNumberOfVectorParms(); ++I) { 928 if (I != 0) 929 ParmsType += ", "; 930 switch (Value & TracebackTable::ParmTypeMask) { 931 case TracebackTable::ParmTypeIsVectorCharBit: 932 ParmsType += "vc"; 933 break; 934 935 case TracebackTable::ParmTypeIsVectorShortBit: 936 ParmsType += "vs"; 937 break; 938 939 case TracebackTable::ParmTypeIsVectorIntBit: 940 ParmsType += "vi"; 941 break; 942 943 case TracebackTable::ParmTypeIsVectorFloatBit: 944 ParmsType += "vf"; 945 break; 946 } 947 Value <<= 2; 948 } 949 return ParmsType; 950 } 951 952 static SmallString<32> parseParmsTypeWithVecInfo(uint32_t Value, 953 unsigned int ParmsNum) { 954 SmallString<32> ParmsType; 955 unsigned I = 0; 956 bool Begin = false; 957 while (I < ParmsNum || Value) { 958 if (Begin) 959 ParmsType += ", "; 960 else 961 Begin = true; 962 963 switch (Value & TracebackTable::ParmTypeMask) { 964 case TracebackTable::ParmTypeIsFixedBits: 965 ParmsType += "i"; 966 ++I; 967 break; 968 case TracebackTable::ParmTypeIsVectorBits: 969 ParmsType += "v"; 970 break; 971 case TracebackTable::ParmTypeIsFloatingBits: 972 ParmsType += "f"; 973 ++I; 974 break; 975 case TracebackTable::ParmTypeIsDoubleBits: 976 ParmsType += "d"; 977 ++I; 978 break; 979 default: 980 assert(false && "Unrecognized bits in ParmsType."); 981 } 982 Value <<= 2; 983 } 984 assert(I == ParmsNum && 985 "The total parameters number of fixed-point or floating-point " 986 "parameters not equal to the number in the parameter type!"); 987 return ParmsType; 988 } 989 990 Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, 991 uint64_t &Size) { 992 Error Err = Error::success(); 993 XCOFFTracebackTable TBT(Ptr, Size, Err); 994 if (Err) 995 return std::move(Err); 996 return TBT; 997 } 998 999 XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, 1000 Error &Err) 1001 : TBPtr(Ptr) { 1002 ErrorAsOutParameter EAO(&Err); 1003 DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, 1004 /*AddressSize=*/0); 1005 DataExtractor::Cursor Cur(/*Offset=*/0); 1006 1007 // Skip 8 bytes of mandatory fields. 1008 DE.getU64(Cur); 1009 1010 // Begin to parse optional fields. 1011 if (Cur) { 1012 unsigned ParmNum = getNumberOfFixedParms() + getNumberOfFPParms(); 1013 1014 // As long as there are no "fixed-point" or floating-point parameters, this 1015 // field remains not present even when hasVectorInfo gives true and 1016 // indicates the presence of vector parameters. 1017 if (ParmNum > 0) { 1018 uint32_t ParamsTypeValue = DE.getU32(Cur); 1019 if (Cur) 1020 ParmsType = hasVectorInfo() 1021 ? parseParmsTypeWithVecInfo(ParamsTypeValue, ParmNum) 1022 : parseParmsType(ParamsTypeValue, ParmNum); 1023 } 1024 } 1025 1026 if (Cur && hasTraceBackTableOffset()) 1027 TraceBackTableOffset = DE.getU32(Cur); 1028 1029 if (Cur && isInterruptHandler()) 1030 HandlerMask = DE.getU32(Cur); 1031 1032 if (Cur && hasControlledStorage()) { 1033 NumOfCtlAnchors = DE.getU32(Cur); 1034 if (Cur && NumOfCtlAnchors) { 1035 SmallVector<uint32_t, 8> Disp; 1036 Disp.reserve(NumOfCtlAnchors.getValue()); 1037 for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) 1038 Disp.push_back(DE.getU32(Cur)); 1039 if (Cur) 1040 ControlledStorageInfoDisp = std::move(Disp); 1041 } 1042 } 1043 1044 if (Cur && isFuncNamePresent()) { 1045 uint16_t FunctionNameLen = DE.getU16(Cur); 1046 if (Cur) 1047 FunctionName = DE.getBytes(Cur, FunctionNameLen); 1048 } 1049 1050 if (Cur && isAllocaUsed()) 1051 AllocaRegister = DE.getU8(Cur); 1052 1053 if (Cur && hasVectorInfo()) { 1054 StringRef VectorExtRef = DE.getBytes(Cur, 6); 1055 if (Cur) 1056 VecExt = TBVectorExt(VectorExtRef); 1057 } 1058 1059 if (Cur && hasExtensionTable()) 1060 ExtensionTable = DE.getU8(Cur); 1061 1062 if (!Cur) 1063 Err = Cur.takeError(); 1064 Size = Cur.tell(); 1065 } 1066 1067 #define GETBITWITHMASK(P, X) \ 1068 (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) 1069 #define GETBITWITHMASKSHIFT(P, X, S) \ 1070 ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ 1071 (TracebackTable::S)) 1072 1073 uint8_t XCOFFTracebackTable::getVersion() const { 1074 return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); 1075 } 1076 1077 uint8_t XCOFFTracebackTable::getLanguageID() const { 1078 return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); 1079 } 1080 1081 bool XCOFFTracebackTable::isGlobalLinkage() const { 1082 return GETBITWITHMASK(0, IsGlobaLinkageMask); 1083 } 1084 1085 bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { 1086 return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); 1087 } 1088 1089 bool XCOFFTracebackTable::hasTraceBackTableOffset() const { 1090 return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); 1091 } 1092 1093 bool XCOFFTracebackTable::isInternalProcedure() const { 1094 return GETBITWITHMASK(0, IsInternalProcedureMask); 1095 } 1096 1097 bool XCOFFTracebackTable::hasControlledStorage() const { 1098 return GETBITWITHMASK(0, HasControlledStorageMask); 1099 } 1100 1101 bool XCOFFTracebackTable::isTOCless() const { 1102 return GETBITWITHMASK(0, IsTOClessMask); 1103 } 1104 1105 bool XCOFFTracebackTable::isFloatingPointPresent() const { 1106 return GETBITWITHMASK(0, IsFloatingPointPresentMask); 1107 } 1108 1109 bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { 1110 return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); 1111 } 1112 1113 bool XCOFFTracebackTable::isInterruptHandler() const { 1114 return GETBITWITHMASK(0, IsInterruptHandlerMask); 1115 } 1116 1117 bool XCOFFTracebackTable::isFuncNamePresent() const { 1118 return GETBITWITHMASK(0, IsFunctionNamePresentMask); 1119 } 1120 1121 bool XCOFFTracebackTable::isAllocaUsed() const { 1122 return GETBITWITHMASK(0, IsAllocaUsedMask); 1123 } 1124 1125 uint8_t XCOFFTracebackTable::getOnConditionDirective() const { 1126 return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, 1127 OnConditionDirectiveShift); 1128 } 1129 1130 bool XCOFFTracebackTable::isCRSaved() const { 1131 return GETBITWITHMASK(0, IsCRSavedMask); 1132 } 1133 1134 bool XCOFFTracebackTable::isLRSaved() const { 1135 return GETBITWITHMASK(0, IsLRSavedMask); 1136 } 1137 1138 bool XCOFFTracebackTable::isBackChainStored() const { 1139 return GETBITWITHMASK(4, IsBackChainStoredMask); 1140 } 1141 1142 bool XCOFFTracebackTable::isFixup() const { 1143 return GETBITWITHMASK(4, IsFixupMask); 1144 } 1145 1146 uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { 1147 return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); 1148 } 1149 1150 bool XCOFFTracebackTable::hasExtensionTable() const { 1151 return GETBITWITHMASK(4, HasExtensionTableMask); 1152 } 1153 1154 bool XCOFFTracebackTable::hasVectorInfo() const { 1155 return GETBITWITHMASK(4, HasVectorInfoMask); 1156 } 1157 1158 uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { 1159 return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); 1160 } 1161 1162 uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { 1163 return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, 1164 NumberOfFixedParmsShift); 1165 } 1166 1167 uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { 1168 return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, 1169 NumberOfFloatingPointParmsShift); 1170 } 1171 1172 bool XCOFFTracebackTable::hasParmsOnStack() const { 1173 return GETBITWITHMASK(4, HasParmsOnStackMask); 1174 } 1175 1176 #undef GETBITWITHMASK 1177 #undef GETBITWITHMASKSHIFT 1178 } // namespace object 1179 } // namespace llvm 1180