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