forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			536 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			536 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file implements an XCOFF specific dumper for llvm-readobj.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "Error.h"
 | 
						|
#include "ObjDumper.h"
 | 
						|
#include "llvm-readobj.h"
 | 
						|
#include "llvm/Object/XCOFFObjectFile.h"
 | 
						|
#include "llvm/Support/ScopedPrinter.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace object;
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
class XCOFFDumper : public ObjDumper {
 | 
						|
  enum {
 | 
						|
    SymbolTypeMask = 0x07,
 | 
						|
    SymbolAlignmentMask = 0xF8,
 | 
						|
    SymbolAlignmentBitOffset = 3
 | 
						|
  };
 | 
						|
 | 
						|
public:
 | 
						|
  XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
 | 
						|
      : ObjDumper(Writer), Obj(Obj) {}
 | 
						|
 | 
						|
  void printFileHeaders() override;
 | 
						|
  void printSectionHeaders() override;
 | 
						|
  void printRelocations() override;
 | 
						|
  void printSymbols() override;
 | 
						|
  void printDynamicSymbols() override;
 | 
						|
  void printUnwindInfo() override;
 | 
						|
  void printStackMap() const override;
 | 
						|
  void printNeededLibraries() override;
 | 
						|
 | 
						|
private:
 | 
						|
  template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
 | 
						|
  template <typename T> void printGenericSectionHeader(T &Sec) const;
 | 
						|
  template <typename T> void printOverflowSectionHeader(T &Sec) const;
 | 
						|
  void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
 | 
						|
  void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
 | 
						|
  void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
 | 
						|
  void printSymbol(const SymbolRef &);
 | 
						|
  void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
 | 
						|
  const XCOFFObjectFile &Obj;
 | 
						|
};
 | 
						|
} // anonymous namespace
 | 
						|
 | 
						|
void XCOFFDumper::printFileHeaders() {
 | 
						|
  DictScope DS(W, "FileHeader");
 | 
						|
  W.printHex("Magic", Obj.getMagic());
 | 
						|
  W.printNumber("NumberOfSections", Obj.getNumberOfSections());
 | 
						|
 | 
						|
  // Negative timestamp values are reserved for future use.
 | 
						|
  int32_t TimeStamp = Obj.getTimeStamp();
 | 
						|
  if (TimeStamp > 0) {
 | 
						|
    // This handling of the time stamp assumes that the host system's time_t is
 | 
						|
    // compatible with AIX time_t. If a platform is not compatible, the lit
 | 
						|
    // tests will let us know.
 | 
						|
    time_t TimeDate = TimeStamp;
 | 
						|
 | 
						|
    char FormattedTime[21] = {};
 | 
						|
    size_t BytesWritten =
 | 
						|
        strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
 | 
						|
    if (BytesWritten)
 | 
						|
      W.printHex("TimeStamp", FormattedTime, TimeStamp);
 | 
						|
    else
 | 
						|
      W.printHex("Timestamp", TimeStamp);
 | 
						|
  } else {
 | 
						|
    W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
 | 
						|
               TimeStamp);
 | 
						|
  }
 | 
						|
 | 
						|
  // The number of symbol table entries is an unsigned value in 64-bit objects
 | 
						|
  // and a signed value (with negative values being 'reserved') in 32-bit
 | 
						|
  // objects.
 | 
						|
  if (Obj.is64Bit()) {
 | 
						|
    W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
 | 
						|
    W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
 | 
						|
  } else {
 | 
						|
    W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
 | 
						|
    int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
 | 
						|
    if (SymTabEntries >= 0)
 | 
						|
      W.printNumber("SymbolTableEntries", SymTabEntries);
 | 
						|
    else
 | 
						|
      W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
 | 
						|
  }
 | 
						|
 | 
						|
  W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
 | 
						|
  W.printHex("Flags", Obj.getFlags());
 | 
						|
 | 
						|
  // TODO FIXME Add support for the auxiliary header (if any) once
 | 
						|
  // XCOFFObjectFile has the necessary support.
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printSectionHeaders() {
 | 
						|
  if (Obj.is64Bit())
 | 
						|
    printSectionHeaders(Obj.sections64());
 | 
						|
  else
 | 
						|
    printSectionHeaders(Obj.sections32());
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printRelocations() {
 | 
						|
  if (Obj.is64Bit())
 | 
						|
    llvm_unreachable("64-bit relocation output not implemented!");
 | 
						|
  else
 | 
						|
    printRelocations(Obj.sections32());
 | 
						|
}
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(R_POS),    ECase(R_RL),     ECase(R_RLA),    ECase(R_NEG),
 | 
						|
    ECase(R_REL),    ECase(R_TOC),    ECase(R_TRL),    ECase(R_TRLA),
 | 
						|
    ECase(R_GL),     ECase(R_TCL),    ECase(R_REF),    ECase(R_BA),
 | 
						|
    ECase(R_BR),     ECase(R_RBA),    ECase(R_RBR),    ECase(R_TLS),
 | 
						|
    ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
 | 
						|
    ECase(R_TLSML),  ECase(R_TOCU),   ECase(R_TOCL)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
void XCOFFDumper::printRelocations(ArrayRef<XCOFFSectionHeader32> Sections) {
 | 
						|
  if (!opts::ExpandRelocs)
 | 
						|
    report_fatal_error("Unexpanded relocation output not implemented.");
 | 
						|
 | 
						|
  ListScope LS(W, "Relocations");
 | 
						|
  uint16_t Index = 0;
 | 
						|
  for (const auto &Sec : Sections) {
 | 
						|
    ++Index;
 | 
						|
    // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
 | 
						|
    if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
 | 
						|
        Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
 | 
						|
      continue;
 | 
						|
    auto Relocations = unwrapOrError(Obj.getFileName(), Obj.relocations(Sec));
 | 
						|
    if (Relocations.empty())
 | 
						|
      continue;
 | 
						|
 | 
						|
    W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
 | 
						|
                  << " {\n";
 | 
						|
    for (auto Reloc : Relocations) {
 | 
						|
      StringRef SymbolName = unwrapOrError(
 | 
						|
          Obj.getFileName(), Obj.getSymbolNameByIndex(Reloc.SymbolIndex));
 | 
						|
 | 
						|
      DictScope RelocScope(W, "Relocation");
 | 
						|
      W.printHex("Virtual Address", Reloc.VirtualAddress);
 | 
						|
      W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
 | 
						|
      W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
 | 
						|
      W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
 | 
						|
      W.printNumber("Length", Reloc.getRelocatedLength());
 | 
						|
      W.printEnum("Type", (uint8_t)Reloc.Type,
 | 
						|
                  makeArrayRef(RelocationTypeNameclass));
 | 
						|
    }
 | 
						|
    W.unindent();
 | 
						|
    W.startLine() << "}\n";
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
 | 
						|
  if (Obj.is64Bit())
 | 
						|
    report_fatal_error(
 | 
						|
        "Printing for File Auxiliary Entry in 64-bit is unimplemented.");
 | 
						|
  StringRef FileName =
 | 
						|
      unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
 | 
						|
  DictScope SymDs(W, "File Auxiliary Entry");
 | 
						|
  W.printNumber("Index",
 | 
						|
                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
 | 
						|
  W.printString("Name", FileName);
 | 
						|
  W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
 | 
						|
              makeArrayRef(FileStringType));
 | 
						|
}
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
 | 
						|
    {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
        ECase(XMC_PR),   ECase(XMC_RO),     ECase(XMC_DB),
 | 
						|
        ECase(XMC_GL),   ECase(XMC_XO),     ECase(XMC_SV),
 | 
						|
        ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI),
 | 
						|
        ECase(XMC_TB),   ECase(XMC_RW),     ECase(XMC_TC0),
 | 
						|
        ECase(XMC_TC),   ECase(XMC_TD),     ECase(XMC_DS),
 | 
						|
        ECase(XMC_UA),   ECase(XMC_BS),     ECase(XMC_UC),
 | 
						|
        ECase(XMC_TL),   ECase(XMC_TE)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
 | 
						|
  assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
 | 
						|
 | 
						|
  DictScope SymDs(W, "CSECT Auxiliary Entry");
 | 
						|
  W.printNumber("Index",
 | 
						|
                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
 | 
						|
  if ((AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask) == XCOFF::XTY_LD)
 | 
						|
    W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
 | 
						|
  else
 | 
						|
    W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
 | 
						|
  W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
 | 
						|
  W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
 | 
						|
  // Print out symbol alignment and type.
 | 
						|
  W.printNumber("SymbolAlignmentLog2",
 | 
						|
                (AuxEntPtr->SymbolAlignmentAndType & SymbolAlignmentMask) >>
 | 
						|
                    SymbolAlignmentBitOffset);
 | 
						|
  W.printEnum("SymbolType", AuxEntPtr->SymbolAlignmentAndType & SymbolTypeMask,
 | 
						|
              makeArrayRef(CsectSymbolTypeClass));
 | 
						|
  W.printEnum("StorageMappingClass",
 | 
						|
              static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
 | 
						|
              makeArrayRef(CsectStorageMappingClass));
 | 
						|
  W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
 | 
						|
  W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printSectAuxEntForStat(
 | 
						|
    const XCOFFSectAuxEntForStat *AuxEntPtr) {
 | 
						|
  assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
 | 
						|
 | 
						|
  DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
 | 
						|
  W.printNumber("Index",
 | 
						|
                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
 | 
						|
  W.printNumber("SectionLength", AuxEntPtr->SectionLength);
 | 
						|
 | 
						|
  // Unlike the corresponding fields in the section header, NumberOfRelocEnt
 | 
						|
  // and NumberOfLineNum do not handle values greater than 65535.
 | 
						|
  W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
 | 
						|
  W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
 | 
						|
}
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(C_NULL),  ECase(C_AUTO),    ECase(C_EXT),     ECase(C_STAT),
 | 
						|
    ECase(C_REG),   ECase(C_EXTDEF),  ECase(C_LABEL),   ECase(C_ULABEL),
 | 
						|
    ECase(C_MOS),   ECase(C_ARG),     ECase(C_STRTAG),  ECase(C_MOU),
 | 
						|
    ECase(C_UNTAG), ECase(C_TPDEF),   ECase(C_USTATIC), ECase(C_ENTAG),
 | 
						|
    ECase(C_MOE),   ECase(C_REGPARM), ECase(C_FIELD),   ECase(C_BLOCK),
 | 
						|
    ECase(C_FCN),   ECase(C_EOS),     ECase(C_FILE),    ECase(C_LINE),
 | 
						|
    ECase(C_ALIAS), ECase(C_HIDDEN),  ECase(C_HIDEXT),  ECase(C_BINCL),
 | 
						|
    ECase(C_EINCL), ECase(C_INFO),    ECase(C_WEAKEXT), ECase(C_DWARF),
 | 
						|
    ECase(C_GSYM),  ECase(C_LSYM),    ECase(C_PSYM),    ECase(C_RSYM),
 | 
						|
    ECase(C_RPSYM), ECase(C_STSYM),   ECase(C_TCSYM),   ECase(C_BCOMM),
 | 
						|
    ECase(C_ECOML), ECase(C_ECOMM),   ECase(C_DECL),    ECase(C_ENTRY),
 | 
						|
    ECase(C_FUN),   ECase(C_BSTAT),   ECase(C_ESTAT),   ECase(C_GTLS),
 | 
						|
    ECase(C_STTLS), ECase(C_EFCN)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
 | 
						|
  switch (SC) {
 | 
						|
  case XCOFF::C_EXT:
 | 
						|
  case XCOFF::C_WEAKEXT:
 | 
						|
  case XCOFF::C_HIDEXT:
 | 
						|
  case XCOFF::C_STAT:
 | 
						|
    return "Value (RelocatableAddress)";
 | 
						|
  case XCOFF::C_FILE:
 | 
						|
    return "Value (SymbolTableIndex)";
 | 
						|
  case XCOFF::C_FCN:
 | 
						|
  case XCOFF::C_BLOCK:
 | 
						|
  case XCOFF::C_FUN:
 | 
						|
  case XCOFF::C_STSYM:
 | 
						|
  case XCOFF::C_BINCL:
 | 
						|
  case XCOFF::C_EINCL:
 | 
						|
  case XCOFF::C_INFO:
 | 
						|
  case XCOFF::C_BSTAT:
 | 
						|
  case XCOFF::C_LSYM:
 | 
						|
  case XCOFF::C_PSYM:
 | 
						|
  case XCOFF::C_RPSYM:
 | 
						|
  case XCOFF::C_RSYM:
 | 
						|
  case XCOFF::C_ECOML:
 | 
						|
  case XCOFF::C_DWARF:
 | 
						|
    assert(false && "This StorageClass for the symbol is not yet implemented.");
 | 
						|
    return "";
 | 
						|
  default:
 | 
						|
    return "Value";
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(TB_C), ECase(TB_CPLUSPLUS)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
void XCOFFDumper::printSymbol(const SymbolRef &S) {
 | 
						|
  if (Obj.is64Bit())
 | 
						|
    report_fatal_error("64-bit support is unimplemented.");
 | 
						|
 | 
						|
  DataRefImpl SymbolDRI = S.getRawDataRefImpl();
 | 
						|
  const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
 | 
						|
 | 
						|
  XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
 | 
						|
  uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
 | 
						|
 | 
						|
  DictScope SymDs(W, "Symbol");
 | 
						|
 | 
						|
  StringRef SymbolName =
 | 
						|
      unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
 | 
						|
 | 
						|
  W.printNumber("Index",
 | 
						|
                Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
 | 
						|
  W.printString("Name", SymbolName);
 | 
						|
  W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
 | 
						|
             SymbolEntPtr->Value);
 | 
						|
 | 
						|
  StringRef SectionName =
 | 
						|
      unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
 | 
						|
 | 
						|
  W.printString("Section", SectionName);
 | 
						|
  if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
 | 
						|
    W.printEnum("Source Language ID",
 | 
						|
                SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
 | 
						|
                makeArrayRef(CFileLangIdClass));
 | 
						|
    W.printEnum("CPU Version ID",
 | 
						|
                SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
 | 
						|
                makeArrayRef(CFileCpuIdClass));
 | 
						|
  } else
 | 
						|
    W.printHex("Type", SymbolEntPtr->SymbolType);
 | 
						|
 | 
						|
  W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
 | 
						|
              makeArrayRef(SymStorageClass));
 | 
						|
  W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
 | 
						|
 | 
						|
  if (NumberOfAuxEntries == 0)
 | 
						|
    return;
 | 
						|
 | 
						|
  switch (XCOFFSymRef.getStorageClass()) {
 | 
						|
  case XCOFF::C_FILE:
 | 
						|
    // If the symbol is C_FILE and has auxiliary entries...
 | 
						|
    for (int i = 1; i <= NumberOfAuxEntries; i++) {
 | 
						|
      const XCOFFFileAuxEnt *FileAuxEntPtr =
 | 
						|
          reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
 | 
						|
#ifndef NDEBUG
 | 
						|
      Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
 | 
						|
#endif
 | 
						|
      printFileAuxEnt(FileAuxEntPtr);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case XCOFF::C_EXT:
 | 
						|
  case XCOFF::C_WEAKEXT:
 | 
						|
  case XCOFF::C_HIDEXT:
 | 
						|
    // If the symbol is for a function, and it has more than 1 auxiliary entry,
 | 
						|
    // then one of them must be function auxiliary entry which we do not
 | 
						|
    // support yet.
 | 
						|
    if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
 | 
						|
      report_fatal_error("Function auxiliary entry printing is unimplemented.");
 | 
						|
 | 
						|
    // If there is more than 1 auxiliary entry, instead of printing out
 | 
						|
    // error information, print out the raw Auxiliary entry from 1st till
 | 
						|
    // the last - 1. The last one must be a CSECT Auxiliary Entry.
 | 
						|
    for (int i = 1; i < NumberOfAuxEntries; i++) {
 | 
						|
      W.startLine() << "!Unexpected raw auxiliary entry data:\n";
 | 
						|
      W.startLine() << format_bytes(
 | 
						|
          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
 | 
						|
                            XCOFF::SymbolTableEntrySize));
 | 
						|
    }
 | 
						|
 | 
						|
    // The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
 | 
						|
    printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
 | 
						|
    break;
 | 
						|
  case XCOFF::C_STAT:
 | 
						|
    if (NumberOfAuxEntries > 1)
 | 
						|
      report_fatal_error(
 | 
						|
          "C_STAT symbol should not have more than 1 auxiliary entry.");
 | 
						|
 | 
						|
    const XCOFFSectAuxEntForStat *StatAuxEntPtr;
 | 
						|
    StatAuxEntPtr =
 | 
						|
        reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
 | 
						|
#ifndef NDEBUG
 | 
						|
    Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
 | 
						|
#endif
 | 
						|
    printSectAuxEntForStat(StatAuxEntPtr);
 | 
						|
    break;
 | 
						|
  case XCOFF::C_DWARF:
 | 
						|
  case XCOFF::C_BLOCK:
 | 
						|
  case XCOFF::C_FCN:
 | 
						|
    report_fatal_error("Symbol table entry printing for this storage class "
 | 
						|
                       "type is unimplemented.");
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    for (int i = 1; i <= NumberOfAuxEntries; i++) {
 | 
						|
      W.startLine() << "!Unexpected raw auxiliary entry data:\n";
 | 
						|
      W.startLine() << format_bytes(
 | 
						|
          ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
 | 
						|
                            XCOFF::SymbolTableEntrySize));
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printSymbols() {
 | 
						|
  ListScope Group(W, "Symbols");
 | 
						|
  for (const SymbolRef &S : Obj.symbols())
 | 
						|
    printSymbol(S);
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printDynamicSymbols() {
 | 
						|
  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printUnwindInfo() {
 | 
						|
  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printStackMap() const {
 | 
						|
  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
 | 
						|
}
 | 
						|
 | 
						|
void XCOFFDumper::printNeededLibraries() {
 | 
						|
  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
 | 
						|
}
 | 
						|
 | 
						|
static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
 | 
						|
#define ECase(X)                                                               \
 | 
						|
  { #X, XCOFF::X }
 | 
						|
    ECase(STYP_PAD),    ECase(STYP_DWARF), ECase(STYP_TEXT),
 | 
						|
    ECase(STYP_DATA),   ECase(STYP_BSS),   ECase(STYP_EXCEPT),
 | 
						|
    ECase(STYP_INFO),   ECase(STYP_TDATA), ECase(STYP_TBSS),
 | 
						|
    ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
 | 
						|
    ECase(STYP_OVRFLO)
 | 
						|
#undef ECase
 | 
						|
};
 | 
						|
 | 
						|
template <typename T>
 | 
						|
void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
 | 
						|
  if (Obj.is64Bit()) {
 | 
						|
    reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
 | 
						|
                                          "contain an overflow section header.",
 | 
						|
                                          object_error::parse_failed),
 | 
						|
                  Obj.getFileName());
 | 
						|
  }
 | 
						|
 | 
						|
  W.printString("Name", Sec.getName());
 | 
						|
  W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
 | 
						|
  W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
 | 
						|
  W.printHex("Size", Sec.SectionSize);
 | 
						|
  W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
 | 
						|
  W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
 | 
						|
  W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
 | 
						|
  W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
 | 
						|
  W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
 | 
						|
}
 | 
						|
 | 
						|
template <typename T>
 | 
						|
void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
 | 
						|
  W.printString("Name", Sec.getName());
 | 
						|
  W.printHex("PhysicalAddress", Sec.PhysicalAddress);
 | 
						|
  W.printHex("VirtualAddress", Sec.VirtualAddress);
 | 
						|
  W.printHex("Size", Sec.SectionSize);
 | 
						|
  W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
 | 
						|
  W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
 | 
						|
  W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
 | 
						|
  W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
 | 
						|
  W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
 | 
						|
}
 | 
						|
 | 
						|
template <typename T>
 | 
						|
void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
 | 
						|
  ListScope Group(W, "Sections");
 | 
						|
 | 
						|
  uint16_t Index = 1;
 | 
						|
  for (const T &Sec : Sections) {
 | 
						|
    DictScope SecDS(W, "Section");
 | 
						|
 | 
						|
    W.printNumber("Index", Index++);
 | 
						|
    uint16_t SectionType = Sec.getSectionType();
 | 
						|
    switch (SectionType) {
 | 
						|
    case XCOFF::STYP_OVRFLO:
 | 
						|
      printOverflowSectionHeader(Sec);
 | 
						|
      break;
 | 
						|
    case XCOFF::STYP_LOADER:
 | 
						|
    case XCOFF::STYP_EXCEPT:
 | 
						|
    case XCOFF::STYP_TYPCHK:
 | 
						|
      // TODO The interpretation of loader, exception and type check section
 | 
						|
      // headers are different from that of generic section headers. We will
 | 
						|
      // implement them later. We interpret them as generic section headers for
 | 
						|
      // now.
 | 
						|
    default:
 | 
						|
      printGenericSectionHeader(Sec);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    if (Sec.isReservedSectionType())
 | 
						|
      W.printHex("Flags", "Reserved", SectionType);
 | 
						|
    else
 | 
						|
      W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
 | 
						|
  }
 | 
						|
 | 
						|
  if (opts::SectionRelocations)
 | 
						|
    report_fatal_error("Dumping section relocations is unimplemented");
 | 
						|
 | 
						|
  if (opts::SectionSymbols)
 | 
						|
    report_fatal_error("Dumping symbols is unimplemented");
 | 
						|
 | 
						|
  if (opts::SectionData)
 | 
						|
    report_fatal_error("Dumping section data is unimplemented");
 | 
						|
}
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
 | 
						|
                                  ScopedPrinter &Writer,
 | 
						|
                                  std::unique_ptr<ObjDumper> &Result) {
 | 
						|
  const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(Obj);
 | 
						|
  if (!XObj)
 | 
						|
    return readobj_error::unsupported_obj_file_format;
 | 
						|
 | 
						|
  Result.reset(new XCOFFDumper(*XObj, Writer));
 | 
						|
  return readobj_error::success;
 | 
						|
}
 | 
						|
} // namespace llvm
 |