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 createStringError(object_error::invalid_section_index, 596 "the section index (" + Twine(Num) + 597 ") is invalid"); 598 599 DataRefImpl DRI; 600 DRI.p = getWithOffset(getSectionHeaderTableAddress(), 601 getSectionHeaderSize() * (Num - 1)); 602 return DRI; 603 } 604 605 Expected<StringRef> 606 XCOFFObjectFile::getSymbolSectionName(XCOFFSymbolRef SymEntPtr) const { 607 const int16_t SectionNum = SymEntPtr.getSectionNumber(); 608 609 switch (SectionNum) { 610 case XCOFF::N_DEBUG: 611 return "N_DEBUG"; 612 case XCOFF::N_ABS: 613 return "N_ABS"; 614 case XCOFF::N_UNDEF: 615 return "N_UNDEF"; 616 default: 617 Expected<DataRefImpl> SecRef = getSectionByNum(SectionNum); 618 if (SecRef) 619 return generateXCOFFFixedNameStringRef( 620 getSectionNameInternal(SecRef.get())); 621 return SecRef.takeError(); 622 } 623 } 624 625 unsigned XCOFFObjectFile::getSymbolSectionID(SymbolRef Sym) const { 626 XCOFFSymbolRef XCOFFSymRef(Sym.getRawDataRefImpl(), this); 627 return XCOFFSymRef.getSectionNumber(); 628 } 629 630 bool XCOFFObjectFile::isReservedSectionNumber(int16_t SectionNumber) { 631 return (SectionNumber <= 0 && SectionNumber >= -2); 632 } 633 634 uint16_t XCOFFObjectFile::getNumberOfSections() const { 635 return is64Bit() ? fileHeader64()->NumberOfSections 636 : fileHeader32()->NumberOfSections; 637 } 638 639 int32_t XCOFFObjectFile::getTimeStamp() const { 640 return is64Bit() ? fileHeader64()->TimeStamp : fileHeader32()->TimeStamp; 641 } 642 643 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const { 644 return is64Bit() ? fileHeader64()->AuxHeaderSize 645 : fileHeader32()->AuxHeaderSize; 646 } 647 648 uint32_t XCOFFObjectFile::getSymbolTableOffset32() const { 649 return fileHeader32()->SymbolTableOffset; 650 } 651 652 int32_t XCOFFObjectFile::getRawNumberOfSymbolTableEntries32() const { 653 // As far as symbol table size is concerned, if this field is negative it is 654 // to be treated as a 0. However since this field is also used for printing we 655 // don't want to truncate any negative values. 656 return fileHeader32()->NumberOfSymTableEntries; 657 } 658 659 uint32_t XCOFFObjectFile::getLogicalNumberOfSymbolTableEntries32() const { 660 return (fileHeader32()->NumberOfSymTableEntries >= 0 661 ? fileHeader32()->NumberOfSymTableEntries 662 : 0); 663 } 664 665 uint64_t XCOFFObjectFile::getSymbolTableOffset64() const { 666 return fileHeader64()->SymbolTableOffset; 667 } 668 669 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries64() const { 670 return fileHeader64()->NumberOfSymTableEntries; 671 } 672 673 uint32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const { 674 return is64Bit() ? getNumberOfSymbolTableEntries64() 675 : getLogicalNumberOfSymbolTableEntries32(); 676 } 677 678 uintptr_t XCOFFObjectFile::getEndOfSymbolTableAddress() const { 679 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 680 return getWithOffset(reinterpret_cast<uintptr_t>(SymbolTblPtr), 681 XCOFF::SymbolTableEntrySize * NumberOfSymTableEntries); 682 } 683 684 void XCOFFObjectFile::checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const { 685 if (SymbolEntPtr < reinterpret_cast<uintptr_t>(SymbolTblPtr)) 686 report_fatal_error("Symbol table entry is outside of symbol table."); 687 688 if (SymbolEntPtr >= getEndOfSymbolTableAddress()) 689 report_fatal_error("Symbol table entry is outside of symbol table."); 690 691 ptrdiff_t Offset = reinterpret_cast<const char *>(SymbolEntPtr) - 692 reinterpret_cast<const char *>(SymbolTblPtr); 693 694 if (Offset % XCOFF::SymbolTableEntrySize != 0) 695 report_fatal_error( 696 "Symbol table entry position is not valid inside of symbol table."); 697 } 698 699 uint32_t XCOFFObjectFile::getSymbolIndex(uintptr_t SymbolEntPtr) const { 700 return (reinterpret_cast<const char *>(SymbolEntPtr) - 701 reinterpret_cast<const char *>(SymbolTblPtr)) / 702 XCOFF::SymbolTableEntrySize; 703 } 704 705 uintptr_t XCOFFObjectFile::getSymbolEntryAddressByIndex(uint32_t Index) const { 706 return getAdvancedSymbolEntryAddress( 707 reinterpret_cast<uintptr_t>(getPointerToSymbolTable()), Index); 708 } 709 710 Expected<StringRef> 711 XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const { 712 const uint32_t NumberOfSymTableEntries = getNumberOfSymbolTableEntries(); 713 714 if (Index >= NumberOfSymTableEntries) 715 return errorCodeToError(object_error::invalid_symbol_index); 716 717 DataRefImpl SymDRI; 718 SymDRI.p = getSymbolEntryAddressByIndex(Index); 719 return getSymbolName(SymDRI); 720 } 721 722 uint16_t XCOFFObjectFile::getFlags() const { 723 return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags; 724 } 725 726 const char *XCOFFObjectFile::getSectionNameInternal(DataRefImpl Sec) const { 727 return is64Bit() ? toSection64(Sec)->Name : toSection32(Sec)->Name; 728 } 729 730 uintptr_t XCOFFObjectFile::getSectionHeaderTableAddress() const { 731 return reinterpret_cast<uintptr_t>(SectionHeaderTable); 732 } 733 734 int32_t XCOFFObjectFile::getSectionFlags(DataRefImpl Sec) const { 735 return is64Bit() ? toSection64(Sec)->Flags : toSection32(Sec)->Flags; 736 } 737 738 XCOFFObjectFile::XCOFFObjectFile(unsigned int Type, MemoryBufferRef Object) 739 : ObjectFile(Type, Object) { 740 assert(Type == Binary::ID_XCOFF32 || Type == Binary::ID_XCOFF64); 741 } 742 743 ArrayRef<XCOFFSectionHeader64> XCOFFObjectFile::sections64() const { 744 assert(is64Bit() && "64-bit interface called for non 64-bit file."); 745 const XCOFFSectionHeader64 *TablePtr = sectionHeaderTable64(); 746 return ArrayRef<XCOFFSectionHeader64>(TablePtr, 747 TablePtr + getNumberOfSections()); 748 } 749 750 ArrayRef<XCOFFSectionHeader32> XCOFFObjectFile::sections32() const { 751 assert(!is64Bit() && "32-bit interface called for non 32-bit file."); 752 const XCOFFSectionHeader32 *TablePtr = sectionHeaderTable32(); 753 return ArrayRef<XCOFFSectionHeader32>(TablePtr, 754 TablePtr + getNumberOfSections()); 755 } 756 757 // In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO 758 // section header contains the actual count of relocation entries in the s_paddr 759 // field. STYP_OVRFLO headers contain the section index of their corresponding 760 // sections as their raw "NumberOfRelocations" field value. 761 template <typename T> 762 Expected<uint32_t> XCOFFObjectFile::getNumberOfRelocationEntries( 763 const XCOFFSectionHeader<T> &Sec) const { 764 const T &Section = static_cast<const T &>(Sec); 765 if (is64Bit()) 766 return Section.NumberOfRelocations; 767 768 uint16_t SectionIndex = &Section - sectionHeaderTable<T>() + 1; 769 if (Section.NumberOfRelocations < XCOFF::RelocOverflow) 770 return Section.NumberOfRelocations; 771 for (const auto &Sec : sections32()) { 772 if (Sec.Flags == XCOFF::STYP_OVRFLO && 773 Sec.NumberOfRelocations == SectionIndex) 774 return Sec.PhysicalAddress; 775 } 776 return errorCodeToError(object_error::parse_failed); 777 } 778 779 template <typename Shdr, typename Reloc> 780 Expected<ArrayRef<Reloc>> XCOFFObjectFile::relocations(const Shdr &Sec) const { 781 uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader), 782 Sec.FileOffsetToRelocationInfo); 783 auto NumRelocEntriesOrErr = getNumberOfRelocationEntries(Sec); 784 if (Error E = NumRelocEntriesOrErr.takeError()) 785 return std::move(E); 786 787 uint32_t NumRelocEntries = NumRelocEntriesOrErr.get(); 788 static_assert((sizeof(Reloc) == XCOFF::RelocationSerializationSize64 || 789 sizeof(Reloc) == XCOFF::RelocationSerializationSize32), 790 "Relocation structure is incorrect"); 791 auto RelocationOrErr = 792 getObject<Reloc>(Data, reinterpret_cast<void *>(RelocAddr), 793 NumRelocEntries * sizeof(Reloc)); 794 if (Error E = RelocationOrErr.takeError()) 795 return std::move(E); 796 797 const Reloc *StartReloc = RelocationOrErr.get(); 798 799 return ArrayRef<Reloc>(StartReloc, StartReloc + NumRelocEntries); 800 } 801 802 Expected<XCOFFStringTable> 803 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) { 804 // If there is a string table, then the buffer must contain at least 4 bytes 805 // for the string table's size. Not having a string table is not an error. 806 if (Error E = Binary::checkOffset( 807 Obj->Data, reinterpret_cast<uintptr_t>(Obj->base() + Offset), 4)) { 808 consumeError(std::move(E)); 809 return XCOFFStringTable{0, nullptr}; 810 } 811 812 // Read the size out of the buffer. 813 uint32_t Size = support::endian::read32be(Obj->base() + Offset); 814 815 // If the size is less then 4, then the string table is just a size and no 816 // string data. 817 if (Size <= 4) 818 return XCOFFStringTable{4, nullptr}; 819 820 auto StringTableOrErr = 821 getObject<char>(Obj->Data, Obj->base() + Offset, Size); 822 if (Error E = StringTableOrErr.takeError()) 823 return std::move(E); 824 825 const char *StringTablePtr = StringTableOrErr.get(); 826 if (StringTablePtr[Size - 1] != '\0') 827 return errorCodeToError(object_error::string_table_non_null_end); 828 829 return XCOFFStringTable{Size, StringTablePtr}; 830 } 831 832 // This function returns the import file table. Each entry in the import file 833 // table consists of: "path_name\0base_name\0archive_member_name\0". 834 Expected<StringRef> XCOFFObjectFile::getImportFileTable() const { 835 Expected<uintptr_t> LoaderSectionAddrOrError = getLoaderSectionAddress(); 836 if (!LoaderSectionAddrOrError) 837 return LoaderSectionAddrOrError.takeError(); 838 839 uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get(); 840 if (!LoaderSectionAddr) 841 return StringRef(); 842 843 uint64_t OffsetToImportFileTable = 0; 844 uint64_t LengthOfImportFileTable = 0; 845 if (is64Bit()) { 846 const LoaderSectionHeader64 *LoaderSec64 = 847 viewAs<LoaderSectionHeader64>(LoaderSectionAddr); 848 OffsetToImportFileTable = LoaderSec64->OffsetToImpid; 849 LengthOfImportFileTable = LoaderSec64->LengthOfImpidStrTbl; 850 } else { 851 const LoaderSectionHeader32 *LoaderSec32 = 852 viewAs<LoaderSectionHeader32>(LoaderSectionAddr); 853 OffsetToImportFileTable = LoaderSec32->OffsetToImpid; 854 LengthOfImportFileTable = LoaderSec32->LengthOfImpidStrTbl; 855 } 856 857 auto ImportTableOrErr = getObject<char>( 858 Data, 859 reinterpret_cast<void *>(LoaderSectionAddr + OffsetToImportFileTable), 860 LengthOfImportFileTable); 861 if (Error E = ImportTableOrErr.takeError()) 862 return std::move(E); 863 864 const char *ImportTablePtr = ImportTableOrErr.get(); 865 if (ImportTablePtr[LengthOfImportFileTable - 1] != '\0') 866 return createStringError( 867 object_error::parse_failed, 868 "the import file table must end with a null terminator"); 869 870 return StringRef(ImportTablePtr, LengthOfImportFileTable); 871 } 872 873 Expected<std::unique_ptr<XCOFFObjectFile>> 874 XCOFFObjectFile::create(unsigned Type, MemoryBufferRef MBR) { 875 // Can't use std::make_unique because of the private constructor. 876 std::unique_ptr<XCOFFObjectFile> Obj; 877 Obj.reset(new XCOFFObjectFile(Type, MBR)); 878 879 uint64_t CurOffset = 0; 880 const auto *Base = Obj->base(); 881 MemoryBufferRef Data = Obj->Data; 882 883 // Parse file header. 884 auto FileHeaderOrErr = 885 getObject<void>(Data, Base + CurOffset, Obj->getFileHeaderSize()); 886 if (Error E = FileHeaderOrErr.takeError()) 887 return std::move(E); 888 Obj->FileHeader = FileHeaderOrErr.get(); 889 890 CurOffset += Obj->getFileHeaderSize(); 891 // TODO FIXME we don't have support for an optional header yet, so just skip 892 // past it. 893 CurOffset += Obj->getOptionalHeaderSize(); 894 895 // Parse the section header table if it is present. 896 if (Obj->getNumberOfSections()) { 897 auto SecHeadersOrErr = getObject<void>(Data, Base + CurOffset, 898 Obj->getNumberOfSections() * 899 Obj->getSectionHeaderSize()); 900 if (Error E = SecHeadersOrErr.takeError()) 901 return std::move(E); 902 Obj->SectionHeaderTable = SecHeadersOrErr.get(); 903 } 904 905 const uint32_t NumberOfSymbolTableEntries = 906 Obj->getNumberOfSymbolTableEntries(); 907 908 // If there is no symbol table we are done parsing the memory buffer. 909 if (NumberOfSymbolTableEntries == 0) 910 return std::move(Obj); 911 912 // Parse symbol table. 913 CurOffset = Obj->is64Bit() ? Obj->getSymbolTableOffset64() 914 : Obj->getSymbolTableOffset32(); 915 const uint64_t SymbolTableSize = 916 static_cast<uint64_t>(XCOFF::SymbolTableEntrySize) * 917 NumberOfSymbolTableEntries; 918 auto SymTableOrErr = 919 getObject<void *>(Data, Base + CurOffset, SymbolTableSize); 920 if (Error E = SymTableOrErr.takeError()) 921 return std::move(E); 922 Obj->SymbolTblPtr = SymTableOrErr.get(); 923 CurOffset += SymbolTableSize; 924 925 // Parse String table. 926 Expected<XCOFFStringTable> StringTableOrErr = 927 parseStringTable(Obj.get(), CurOffset); 928 if (Error E = StringTableOrErr.takeError()) 929 return std::move(E); 930 Obj->StringTable = StringTableOrErr.get(); 931 932 return std::move(Obj); 933 } 934 935 Expected<std::unique_ptr<ObjectFile>> 936 ObjectFile::createXCOFFObjectFile(MemoryBufferRef MemBufRef, 937 unsigned FileType) { 938 return XCOFFObjectFile::create(FileType, MemBufRef); 939 } 940 941 bool XCOFFSymbolRef::isFunction() const { 942 if (!isCsectSymbol()) 943 return false; 944 945 if (getSymbolType() & FunctionSym) 946 return true; 947 948 Expected<XCOFFCsectAuxRef> ExpCsectAuxEnt = getXCOFFCsectAuxRef(); 949 if (!ExpCsectAuxEnt) 950 return false; 951 952 const XCOFFCsectAuxRef CsectAuxRef = ExpCsectAuxEnt.get(); 953 954 // A function definition should be a label definition. 955 // FIXME: This is not necessarily the case when -ffunction-sections is 956 // enabled. 957 if (!CsectAuxRef.isLabel()) 958 return false; 959 960 if (CsectAuxRef.getStorageMappingClass() != XCOFF::XMC_PR) 961 return false; 962 963 const int16_t SectNum = getSectionNumber(); 964 Expected<DataRefImpl> SI = OwningObjectPtr->getSectionByNum(SectNum); 965 if (!SI) { 966 // If we could not get the section, then this symbol should not be 967 // a function. So consume the error and return `false` to move on. 968 consumeError(SI.takeError()); 969 return false; 970 } 971 972 return (OwningObjectPtr->getSectionFlags(SI.get()) & XCOFF::STYP_TEXT); 973 } 974 975 bool XCOFFSymbolRef::isCsectSymbol() const { 976 XCOFF::StorageClass SC = getStorageClass(); 977 return (SC == XCOFF::C_EXT || SC == XCOFF::C_WEAKEXT || 978 SC == XCOFF::C_HIDEXT); 979 } 980 981 Expected<XCOFFCsectAuxRef> XCOFFSymbolRef::getXCOFFCsectAuxRef() const { 982 assert(isCsectSymbol() && 983 "Calling csect symbol interface with a non-csect symbol."); 984 985 uint8_t NumberOfAuxEntries = getNumberOfAuxEntries(); 986 987 Expected<StringRef> NameOrErr = getName(); 988 if (auto Err = NameOrErr.takeError()) 989 return std::move(Err); 990 991 if (!NumberOfAuxEntries) { 992 return createStringError(object_error::parse_failed, 993 "csect symbol \"" + *NameOrErr + 994 "\" contains no auxiliary entry"); 995 } 996 997 if (!OwningObjectPtr->is64Bit()) { 998 // In XCOFF32, the csect auxilliary entry is always the last auxiliary 999 // entry for the symbol. 1000 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 1001 getEntryAddress(), NumberOfAuxEntries); 1002 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt32>(AuxAddr)); 1003 } 1004 1005 // XCOFF64 uses SymbolAuxType to identify the auxiliary entry type. 1006 // We need to iterate through all the auxiliary entries to find it. 1007 for (uint8_t Index = NumberOfAuxEntries; Index > 0; --Index) { 1008 uintptr_t AuxAddr = XCOFFObjectFile::getAdvancedSymbolEntryAddress( 1009 getEntryAddress(), Index); 1010 if (*OwningObjectPtr->getSymbolAuxType(AuxAddr) == 1011 XCOFF::SymbolAuxType::AUX_CSECT) { 1012 #ifndef NDEBUG 1013 OwningObjectPtr->checkSymbolEntryPointer(AuxAddr); 1014 #endif 1015 return XCOFFCsectAuxRef(viewAs<XCOFFCsectAuxEnt64>(AuxAddr)); 1016 } 1017 } 1018 1019 return createStringError( 1020 object_error::parse_failed, 1021 "a csect auxiliary entry is not found for symbol \"" + *NameOrErr + "\""); 1022 } 1023 1024 Expected<StringRef> XCOFFSymbolRef::getName() const { 1025 // A storage class value with the high-order bit on indicates that the name is 1026 // a symbolic debugger stabstring. 1027 if (getStorageClass() & 0x80) 1028 return StringRef("Unimplemented Debug Name"); 1029 1030 if (Entry32) { 1031 if (Entry32->NameInStrTbl.Magic != XCOFFSymbolRef::NAME_IN_STR_TBL_MAGIC) 1032 return generateXCOFFFixedNameStringRef(Entry32->SymbolName); 1033 1034 return OwningObjectPtr->getStringTableEntry(Entry32->NameInStrTbl.Offset); 1035 } 1036 1037 return OwningObjectPtr->getStringTableEntry(Entry64->Offset); 1038 } 1039 1040 // Explictly instantiate template classes. 1041 template struct XCOFFSectionHeader<XCOFFSectionHeader32>; 1042 template struct XCOFFSectionHeader<XCOFFSectionHeader64>; 1043 1044 template struct XCOFFRelocation<llvm::support::ubig32_t>; 1045 template struct XCOFFRelocation<llvm::support::ubig64_t>; 1046 1047 template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation64>> 1048 llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader64, 1049 llvm::object::XCOFFRelocation64>( 1050 llvm::object::XCOFFSectionHeader64 const &) const; 1051 template llvm::Expected<llvm::ArrayRef<llvm::object::XCOFFRelocation32>> 1052 llvm::object::XCOFFObjectFile::relocations<llvm::object::XCOFFSectionHeader32, 1053 llvm::object::XCOFFRelocation32>( 1054 llvm::object::XCOFFSectionHeader32 const &) const; 1055 1056 bool doesXCOFFTracebackTableBegin(ArrayRef<uint8_t> Bytes) { 1057 if (Bytes.size() < 4) 1058 return false; 1059 1060 return support::endian::read32be(Bytes.data()) == 0; 1061 } 1062 1063 #define GETVALUEWITHMASK(X) (Data & (TracebackTable::X)) 1064 #define GETVALUEWITHMASKSHIFT(X, S) \ 1065 ((Data & (TracebackTable::X)) >> (TracebackTable::S)) 1066 1067 Expected<TBVectorExt> TBVectorExt::create(StringRef TBvectorStrRef) { 1068 Error Err = Error::success(); 1069 TBVectorExt TBTVecExt(TBvectorStrRef, Err); 1070 if (Err) 1071 return std::move(Err); 1072 return TBTVecExt; 1073 } 1074 1075 TBVectorExt::TBVectorExt(StringRef TBvectorStrRef, Error &Err) { 1076 const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(TBvectorStrRef.data()); 1077 Data = support::endian::read16be(Ptr); 1078 uint32_t VecParmsTypeValue = support::endian::read32be(Ptr + 2); 1079 unsigned ParmsNum = 1080 GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, NumberOfVectorParmsShift); 1081 1082 ErrorAsOutParameter EAO(&Err); 1083 Expected<SmallString<32>> VecParmsTypeOrError = 1084 parseVectorParmsType(VecParmsTypeValue, ParmsNum); 1085 if (!VecParmsTypeOrError) 1086 Err = VecParmsTypeOrError.takeError(); 1087 else 1088 VecParmsInfo = VecParmsTypeOrError.get(); 1089 } 1090 1091 uint8_t TBVectorExt::getNumberOfVRSaved() const { 1092 return GETVALUEWITHMASKSHIFT(NumberOfVRSavedMask, NumberOfVRSavedShift); 1093 } 1094 1095 bool TBVectorExt::isVRSavedOnStack() const { 1096 return GETVALUEWITHMASK(IsVRSavedOnStackMask); 1097 } 1098 1099 bool TBVectorExt::hasVarArgs() const { 1100 return GETVALUEWITHMASK(HasVarArgsMask); 1101 } 1102 1103 uint8_t TBVectorExt::getNumberOfVectorParms() const { 1104 return GETVALUEWITHMASKSHIFT(NumberOfVectorParmsMask, 1105 NumberOfVectorParmsShift); 1106 } 1107 1108 bool TBVectorExt::hasVMXInstruction() const { 1109 return GETVALUEWITHMASK(HasVMXInstructionMask); 1110 } 1111 #undef GETVALUEWITHMASK 1112 #undef GETVALUEWITHMASKSHIFT 1113 1114 Expected<XCOFFTracebackTable> XCOFFTracebackTable::create(const uint8_t *Ptr, 1115 uint64_t &Size) { 1116 Error Err = Error::success(); 1117 XCOFFTracebackTable TBT(Ptr, Size, Err); 1118 if (Err) 1119 return std::move(Err); 1120 return TBT; 1121 } 1122 1123 XCOFFTracebackTable::XCOFFTracebackTable(const uint8_t *Ptr, uint64_t &Size, 1124 Error &Err) 1125 : TBPtr(Ptr) { 1126 ErrorAsOutParameter EAO(&Err); 1127 DataExtractor DE(ArrayRef<uint8_t>(Ptr, Size), /*IsLittleEndian=*/false, 1128 /*AddressSize=*/0); 1129 DataExtractor::Cursor Cur(/*Offset=*/0); 1130 1131 // Skip 8 bytes of mandatory fields. 1132 DE.getU64(Cur); 1133 1134 unsigned FixedParmsNum = getNumberOfFixedParms(); 1135 unsigned FloatingParmsNum = getNumberOfFPParms(); 1136 uint32_t ParamsTypeValue = 0; 1137 1138 // Begin to parse optional fields. 1139 if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) 1140 ParamsTypeValue = DE.getU32(Cur); 1141 1142 if (Cur && hasTraceBackTableOffset()) 1143 TraceBackTableOffset = DE.getU32(Cur); 1144 1145 if (Cur && isInterruptHandler()) 1146 HandlerMask = DE.getU32(Cur); 1147 1148 if (Cur && hasControlledStorage()) { 1149 NumOfCtlAnchors = DE.getU32(Cur); 1150 if (Cur && NumOfCtlAnchors) { 1151 SmallVector<uint32_t, 8> Disp; 1152 Disp.reserve(NumOfCtlAnchors.getValue()); 1153 for (uint32_t I = 0; I < NumOfCtlAnchors && Cur; ++I) 1154 Disp.push_back(DE.getU32(Cur)); 1155 if (Cur) 1156 ControlledStorageInfoDisp = std::move(Disp); 1157 } 1158 } 1159 1160 if (Cur && isFuncNamePresent()) { 1161 uint16_t FunctionNameLen = DE.getU16(Cur); 1162 if (Cur) 1163 FunctionName = DE.getBytes(Cur, FunctionNameLen); 1164 } 1165 1166 if (Cur && isAllocaUsed()) 1167 AllocaRegister = DE.getU8(Cur); 1168 1169 unsigned VectorParmsNum = 0; 1170 if (Cur && hasVectorInfo()) { 1171 StringRef VectorExtRef = DE.getBytes(Cur, 6); 1172 if (Cur) { 1173 Expected<TBVectorExt> TBVecExtOrErr = TBVectorExt::create(VectorExtRef); 1174 if (!TBVecExtOrErr) { 1175 Err = TBVecExtOrErr.takeError(); 1176 return; 1177 } 1178 VecExt = TBVecExtOrErr.get(); 1179 VectorParmsNum = VecExt.getValue().getNumberOfVectorParms(); 1180 } 1181 } 1182 1183 // As long as there is no fixed-point or floating-point parameter, this 1184 // field remains not present even when hasVectorInfo gives true and 1185 // indicates the presence of vector parameters. 1186 if (Cur && (FixedParmsNum + FloatingParmsNum) > 0) { 1187 Expected<SmallString<32>> ParmsTypeOrError = 1188 hasVectorInfo() 1189 ? parseParmsTypeWithVecInfo(ParamsTypeValue, FixedParmsNum, 1190 FloatingParmsNum, VectorParmsNum) 1191 : parseParmsType(ParamsTypeValue, FixedParmsNum, FloatingParmsNum); 1192 1193 if (!ParmsTypeOrError) { 1194 Err = ParmsTypeOrError.takeError(); 1195 return; 1196 } 1197 ParmsType = ParmsTypeOrError.get(); 1198 } 1199 1200 if (Cur && hasExtensionTable()) 1201 ExtensionTable = DE.getU8(Cur); 1202 1203 if (!Cur) 1204 Err = Cur.takeError(); 1205 1206 Size = Cur.tell(); 1207 } 1208 1209 #define GETBITWITHMASK(P, X) \ 1210 (support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) 1211 #define GETBITWITHMASKSHIFT(P, X, S) \ 1212 ((support::endian::read32be(TBPtr + (P)) & (TracebackTable::X)) >> \ 1213 (TracebackTable::S)) 1214 1215 uint8_t XCOFFTracebackTable::getVersion() const { 1216 return GETBITWITHMASKSHIFT(0, VersionMask, VersionShift); 1217 } 1218 1219 uint8_t XCOFFTracebackTable::getLanguageID() const { 1220 return GETBITWITHMASKSHIFT(0, LanguageIdMask, LanguageIdShift); 1221 } 1222 1223 bool XCOFFTracebackTable::isGlobalLinkage() const { 1224 return GETBITWITHMASK(0, IsGlobaLinkageMask); 1225 } 1226 1227 bool XCOFFTracebackTable::isOutOfLineEpilogOrPrologue() const { 1228 return GETBITWITHMASK(0, IsOutOfLineEpilogOrPrologueMask); 1229 } 1230 1231 bool XCOFFTracebackTable::hasTraceBackTableOffset() const { 1232 return GETBITWITHMASK(0, HasTraceBackTableOffsetMask); 1233 } 1234 1235 bool XCOFFTracebackTable::isInternalProcedure() const { 1236 return GETBITWITHMASK(0, IsInternalProcedureMask); 1237 } 1238 1239 bool XCOFFTracebackTable::hasControlledStorage() const { 1240 return GETBITWITHMASK(0, HasControlledStorageMask); 1241 } 1242 1243 bool XCOFFTracebackTable::isTOCless() const { 1244 return GETBITWITHMASK(0, IsTOClessMask); 1245 } 1246 1247 bool XCOFFTracebackTable::isFloatingPointPresent() const { 1248 return GETBITWITHMASK(0, IsFloatingPointPresentMask); 1249 } 1250 1251 bool XCOFFTracebackTable::isFloatingPointOperationLogOrAbortEnabled() const { 1252 return GETBITWITHMASK(0, IsFloatingPointOperationLogOrAbortEnabledMask); 1253 } 1254 1255 bool XCOFFTracebackTable::isInterruptHandler() const { 1256 return GETBITWITHMASK(0, IsInterruptHandlerMask); 1257 } 1258 1259 bool XCOFFTracebackTable::isFuncNamePresent() const { 1260 return GETBITWITHMASK(0, IsFunctionNamePresentMask); 1261 } 1262 1263 bool XCOFFTracebackTable::isAllocaUsed() const { 1264 return GETBITWITHMASK(0, IsAllocaUsedMask); 1265 } 1266 1267 uint8_t XCOFFTracebackTable::getOnConditionDirective() const { 1268 return GETBITWITHMASKSHIFT(0, OnConditionDirectiveMask, 1269 OnConditionDirectiveShift); 1270 } 1271 1272 bool XCOFFTracebackTable::isCRSaved() const { 1273 return GETBITWITHMASK(0, IsCRSavedMask); 1274 } 1275 1276 bool XCOFFTracebackTable::isLRSaved() const { 1277 return GETBITWITHMASK(0, IsLRSavedMask); 1278 } 1279 1280 bool XCOFFTracebackTable::isBackChainStored() const { 1281 return GETBITWITHMASK(4, IsBackChainStoredMask); 1282 } 1283 1284 bool XCOFFTracebackTable::isFixup() const { 1285 return GETBITWITHMASK(4, IsFixupMask); 1286 } 1287 1288 uint8_t XCOFFTracebackTable::getNumOfFPRsSaved() const { 1289 return GETBITWITHMASKSHIFT(4, FPRSavedMask, FPRSavedShift); 1290 } 1291 1292 bool XCOFFTracebackTable::hasExtensionTable() const { 1293 return GETBITWITHMASK(4, HasExtensionTableMask); 1294 } 1295 1296 bool XCOFFTracebackTable::hasVectorInfo() const { 1297 return GETBITWITHMASK(4, HasVectorInfoMask); 1298 } 1299 1300 uint8_t XCOFFTracebackTable::getNumOfGPRsSaved() const { 1301 return GETBITWITHMASKSHIFT(4, GPRSavedMask, GPRSavedShift); 1302 } 1303 1304 uint8_t XCOFFTracebackTable::getNumberOfFixedParms() const { 1305 return GETBITWITHMASKSHIFT(4, NumberOfFixedParmsMask, 1306 NumberOfFixedParmsShift); 1307 } 1308 1309 uint8_t XCOFFTracebackTable::getNumberOfFPParms() const { 1310 return GETBITWITHMASKSHIFT(4, NumberOfFloatingPointParmsMask, 1311 NumberOfFloatingPointParmsShift); 1312 } 1313 1314 bool XCOFFTracebackTable::hasParmsOnStack() const { 1315 return GETBITWITHMASK(4, HasParmsOnStackMask); 1316 } 1317 1318 #undef GETBITWITHMASK 1319 #undef GETBITWITHMASKSHIFT 1320 } // namespace object 1321 } // namespace llvm 1322