brintos

brintos / llvm-project-archived public Read only

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