brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.0 KiB · 4b9ebb8 Raw
416 lines · cpp
1//===------ xcoff2yaml.cpp - XCOFF YAMLIO implementation --------*- C++ -*-===//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#include "obj2yaml.h"10#include "llvm/Object/XCOFFObjectFile.h"11#include "llvm/ObjectYAML/XCOFFYAML.h"12#include "llvm/Support/Errc.h"13#include "llvm/Support/YAMLTraits.h"14 15using namespace llvm;16using namespace llvm::object;17namespace {18 19class XCOFFDumper {20  const object::XCOFFObjectFile &Obj;21  XCOFFYAML::Object YAMLObj;22  void dumpHeader();23  Error dumpSections();24  Error dumpSymbols();25  template <typename Shdr, typename Reloc>26  Error dumpSections(ArrayRef<Shdr> Sections);27 28  // Dump auxiliary symbols.29  Error dumpFileAuxSym(XCOFFYAML::Symbol &Sym,30                       const XCOFFSymbolRef &SymbolEntRef);31  Error dumpStatAuxSym(XCOFFYAML::Symbol &Sym,32                       const XCOFFSymbolRef &SymbolEntRef);33  Error dumpBlockAuxSym(XCOFFYAML::Symbol &Sym,34                        const XCOFFSymbolRef &SymbolEntRef);35  Error dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym,36                        const XCOFFSymbolRef &SymbolEntRef);37  Error dumpAuxSyms(XCOFFYAML::Symbol &Sym, const XCOFFSymbolRef &SymbolEntRef);38  void dumpFuncAuxSym(XCOFFYAML::Symbol &Sym, const uintptr_t AuxAddress);39  void dumpExpAuxSym(XCOFFYAML::Symbol &Sym, const uintptr_t AuxAddress);40  void dumpCsectAuxSym(XCOFFYAML::Symbol &Sym,41                       const object::XCOFFCsectAuxRef &AuxEntPtr);42 43public:44  XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {}45  Error dump();46  XCOFFYAML::Object &getYAMLObj() { return YAMLObj; }47 48  template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress) {49    Obj.checkSymbolEntryPointer(AuxAddress);50    return reinterpret_cast<const T *>(AuxAddress);51  }52};53} // namespace54 55Error XCOFFDumper::dump() {56  dumpHeader();57  if (Error E = dumpSections())58    return E;59  return dumpSymbols();60}61 62void XCOFFDumper::dumpHeader() {63  YAMLObj.Header.Magic = Obj.getMagic();64  YAMLObj.Header.NumberOfSections = Obj.getNumberOfSections();65  YAMLObj.Header.TimeStamp = Obj.getTimeStamp();66  YAMLObj.Header.SymbolTableOffset = Obj.is64Bit()67                                         ? Obj.getSymbolTableOffset64()68                                         : Obj.getSymbolTableOffset32();69  YAMLObj.Header.NumberOfSymTableEntries =70      Obj.is64Bit() ? Obj.getNumberOfSymbolTableEntries64()71                    : Obj.getRawNumberOfSymbolTableEntries32();72  YAMLObj.Header.AuxHeaderSize = Obj.getOptionalHeaderSize();73  YAMLObj.Header.Flags = Obj.getFlags();74}75 76Error XCOFFDumper::dumpSections() {77  if (Obj.is64Bit())78    return dumpSections<XCOFFSectionHeader64, XCOFFRelocation64>(79        Obj.sections64());80  return dumpSections<XCOFFSectionHeader32, XCOFFRelocation32>(81      Obj.sections32());82}83 84template <typename Shdr, typename Reloc>85Error XCOFFDumper::dumpSections(ArrayRef<Shdr> Sections) {86  std::vector<XCOFFYAML::Section> &YamlSections = YAMLObj.Sections;87  for (const Shdr &S : Sections) {88    XCOFFYAML::Section YamlSec;89    YamlSec.SectionName = S.getName();90    YamlSec.Address = S.PhysicalAddress;91    YamlSec.Size = S.SectionSize;92    YamlSec.NumberOfRelocations = S.NumberOfRelocations;93    YamlSec.NumberOfLineNumbers = S.NumberOfLineNumbers;94    YamlSec.FileOffsetToData = S.FileOffsetToRawData;95    YamlSec.FileOffsetToRelocations = S.FileOffsetToRelocationInfo;96    YamlSec.FileOffsetToLineNumbers = S.FileOffsetToLineNumberInfo;97    YamlSec.Flags = S.Flags;98    if (YamlSec.Flags & XCOFF::STYP_DWARF) {99      unsigned Mask = Obj.is64Bit()100                          ? XCOFFSectionHeader64::SectionFlagsTypeMask101                          : XCOFFSectionHeader32::SectionFlagsTypeMask;102      YamlSec.SectionSubtype =103          static_cast<XCOFF::DwarfSectionSubtypeFlags>(S.Flags & ~Mask);104    }105 106    // Dump section data.107    if (S.FileOffsetToRawData) {108      DataRefImpl SectionDRI;109      SectionDRI.p = reinterpret_cast<uintptr_t>(&S);110      Expected<ArrayRef<uint8_t>> SecDataRefOrErr =111          Obj.getSectionContents(SectionDRI);112      if (!SecDataRefOrErr)113        return SecDataRefOrErr.takeError();114      YamlSec.SectionData = SecDataRefOrErr.get();115    }116 117    // Dump relocations.118    if (S.NumberOfRelocations) {119      auto RelRefOrErr = Obj.relocations<Shdr, Reloc>(S);120      if (!RelRefOrErr)121        return RelRefOrErr.takeError();122      for (const Reloc &R : RelRefOrErr.get()) {123        XCOFFYAML::Relocation YamlRel;124        YamlRel.Type = R.Type;125        YamlRel.Info = R.Info;126        YamlRel.SymbolIndex = R.SymbolIndex;127        YamlRel.VirtualAddress = R.VirtualAddress;128        YamlSec.Relocations.push_back(YamlRel);129      }130    }131    YamlSections.push_back(YamlSec);132  }133  return Error::success();134}135 136Error XCOFFDumper::dumpFileAuxSym(XCOFFYAML::Symbol &Sym,137                                  const XCOFFSymbolRef &SymbolEntRef) {138  for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) {139    uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(140        SymbolEntRef.getEntryAddress(), I);141    const XCOFFFileAuxEnt *FileAuxEntPtr =142        getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);143    auto FileNameOrError = Obj.getCFileName(FileAuxEntPtr);144    if (!FileNameOrError)145      return FileNameOrError.takeError();146 147    XCOFFYAML::FileAuxEnt FileAuxSym;148    FileAuxSym.FileNameOrString = FileNameOrError.get();149    FileAuxSym.FileStringType = FileAuxEntPtr->Type;150    Sym.AuxEntries.push_back(151        std::make_unique<XCOFFYAML::FileAuxEnt>(FileAuxSym));152  }153  return Error::success();154}155 156Error XCOFFDumper::dumpStatAuxSym(XCOFFYAML::Symbol &Sym,157                                  const XCOFFSymbolRef &SymbolEntRef) {158  if (Sym.NumberOfAuxEntries != 1) {159    uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());160    return createError("failed to parse symbol \"" + Sym.SymbolName +161                       "\" with index of " + Twine(SymbolIndex) +162                       ": expected 1 aux symbol for C_STAT, while got " +163                       Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));164  }165 166  const XCOFFSectAuxEntForStat *AuxEntPtr =167      getAuxEntPtr<XCOFFSectAuxEntForStat>(168          XCOFFObjectFile::getAdvancedSymbolEntryAddress(169              SymbolEntRef.getEntryAddress(), 1));170  XCOFFYAML::SectAuxEntForStat StatAuxSym;171  StatAuxSym.SectionLength = AuxEntPtr->SectionLength;172  StatAuxSym.NumberOfLineNum = AuxEntPtr->NumberOfLineNum;173  StatAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;174  Sym.AuxEntries.push_back(175      std::make_unique<XCOFFYAML::SectAuxEntForStat>(StatAuxSym));176  return Error::success();177}178 179void XCOFFDumper::dumpFuncAuxSym(XCOFFYAML::Symbol &Sym,180                                 const uintptr_t AuxAddress) {181  XCOFFYAML::FunctionAuxEnt FunAuxSym;182 183  if (Obj.is64Bit()) {184    const XCOFFFunctionAuxEnt64 *AuxEntPtr =185        getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);186    FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum;187    FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;188    FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;189  } else {190    const XCOFFFunctionAuxEnt32 *AuxEntPtr =191        getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);192    FunAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl;193    FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum;194    FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;195    FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;196  }197 198  Sym.AuxEntries.push_back(199      std::make_unique<XCOFFYAML::FunctionAuxEnt>(FunAuxSym));200}201 202void XCOFFDumper::dumpExpAuxSym(XCOFFYAML::Symbol &Sym,203                                const uintptr_t AuxAddress) {204  const XCOFFExceptionAuxEnt *AuxEntPtr =205      getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);206  XCOFFYAML::ExcpetionAuxEnt ExceptAuxSym;207  ExceptAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl;208  ExceptAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;209  ExceptAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;210  Sym.AuxEntries.push_back(211      std::make_unique<XCOFFYAML::ExcpetionAuxEnt>(ExceptAuxSym));212}213 214void XCOFFDumper::dumpCsectAuxSym(XCOFFYAML::Symbol &Sym,215                                  const object::XCOFFCsectAuxRef &AuxEntPtr) {216  XCOFFYAML::CsectAuxEnt CsectAuxSym;217  CsectAuxSym.ParameterHashIndex = AuxEntPtr.getParameterHashIndex();218  CsectAuxSym.TypeChkSectNum = AuxEntPtr.getTypeChkSectNum();219  CsectAuxSym.SymbolAlignment = AuxEntPtr.getAlignmentLog2();220  CsectAuxSym.SymbolType =221      static_cast<XCOFF::SymbolType>(AuxEntPtr.getSymbolType());222  CsectAuxSym.StorageMappingClass = AuxEntPtr.getStorageMappingClass();223 224  if (Obj.is64Bit()) {225    CsectAuxSym.SectionOrLengthLo =226        static_cast<uint32_t>(AuxEntPtr.getSectionOrLength64());227    CsectAuxSym.SectionOrLengthHi =228        static_cast<uint32_t>(AuxEntPtr.getSectionOrLength64() >> 32);229  } else {230    CsectAuxSym.SectionOrLength = AuxEntPtr.getSectionOrLength32();231    CsectAuxSym.StabInfoIndex = AuxEntPtr.getStabInfoIndex32();232    CsectAuxSym.StabSectNum = AuxEntPtr.getStabSectNum32();233  }234 235  Sym.AuxEntries.push_back(236      std::make_unique<XCOFFYAML::CsectAuxEnt>(CsectAuxSym));237}238 239Error XCOFFDumper::dumpAuxSyms(XCOFFYAML::Symbol &Sym,240                               const XCOFFSymbolRef &SymbolEntRef) {241  auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();242  if (!ErrOrCsectAuxRef)243    return ErrOrCsectAuxRef.takeError();244  XCOFFCsectAuxRef CsectAuxRef = ErrOrCsectAuxRef.get();245 246  for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) {247 248    if (I == Sym.NumberOfAuxEntries && !Obj.is64Bit()) {249      dumpCsectAuxSym(Sym, CsectAuxRef);250      return Error::success();251    }252 253    uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(254        SymbolEntRef.getEntryAddress(), I);255 256    if (Obj.is64Bit()) {257      XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);258      if (Type == XCOFF::SymbolAuxType::AUX_CSECT)259        dumpCsectAuxSym(Sym, CsectAuxRef);260      else if (Type == XCOFF::SymbolAuxType::AUX_FCN)261        dumpFuncAuxSym(Sym, AuxAddress);262      else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT)263        dumpExpAuxSym(Sym, AuxAddress);264      else {265        uint32_t SymbolIndex =266            Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());267        return createError("failed to parse symbol \"" + Sym.SymbolName +268                           "\" with index of " + Twine(SymbolIndex) +269                           ": invalid auxiliary symbol type: " +270                           Twine(static_cast<uint32_t>(Type)));271      }272 273    } else274      dumpFuncAuxSym(Sym, AuxAddress);275  }276 277  return Error::success();278}279 280Error XCOFFDumper::dumpBlockAuxSym(XCOFFYAML::Symbol &Sym,281                                   const XCOFFSymbolRef &SymbolEntRef) {282  if (Sym.NumberOfAuxEntries != 1) {283    uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());284    return createError(285        "failed to parse symbol \"" + Sym.SymbolName + "\" with index of " +286        Twine(SymbolIndex) +287        ": expected 1 aux symbol for C_BLOCK or C_FCN, while got " +288        Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));289  }290 291  uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(292      SymbolEntRef.getEntryAddress(), 1);293  XCOFFYAML::BlockAuxEnt BlockAuxSym;294 295  if (Obj.is64Bit()) {296    const XCOFFBlockAuxEnt64 *AuxEntPtr =297        getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);298    BlockAuxSym.LineNum = AuxEntPtr->LineNum;299  } else {300    const XCOFFBlockAuxEnt32 *AuxEntPtr =301        getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);302    BlockAuxSym.LineNumLo = AuxEntPtr->LineNumLo;303    BlockAuxSym.LineNumHi = AuxEntPtr->LineNumHi;304  }305 306  Sym.AuxEntries.push_back(307      std::make_unique<XCOFFYAML::BlockAuxEnt>(BlockAuxSym));308  return Error::success();309}310 311Error XCOFFDumper::dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym,312                                   const XCOFFSymbolRef &SymbolEntRef) {313  if (Sym.NumberOfAuxEntries != 1) {314    uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());315    return createError("failed to parse symbol \"" + Sym.SymbolName +316                       "\" with index of " + Twine(SymbolIndex) +317                       ": expected 1 aux symbol for C_DWARF, while got " +318                       Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));319  }320 321  uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(322      SymbolEntRef.getEntryAddress(), 1);323  XCOFFYAML::SectAuxEntForDWARF DwarfAuxSym;324 325  if (Obj.is64Bit()) {326    const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =327        getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);328    DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion;329    DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;330  } else {331    const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =332        getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);333    DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion;334    DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;335  }336 337  Sym.AuxEntries.push_back(338      std::make_unique<XCOFFYAML::SectAuxEntForDWARF>(DwarfAuxSym));339  return Error::success();340}341 342Error XCOFFDumper::dumpSymbols() {343  std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols;344 345  for (const SymbolRef &S : Obj.symbols()) {346    DataRefImpl SymbolDRI = S.getRawDataRefImpl();347    const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);348    XCOFFYAML::Symbol Sym;349 350    Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);351    if (!SymNameRefOrErr) {352      return SymNameRefOrErr.takeError();353    }354    Sym.SymbolName = SymNameRefOrErr.get();355 356    Sym.Value = SymbolEntRef.getValue();357 358    Expected<StringRef> SectionNameRefOrErr =359        Obj.getSymbolSectionName(SymbolEntRef);360    if (!SectionNameRefOrErr)361      return SectionNameRefOrErr.takeError();362 363    Sym.SectionName = SectionNameRefOrErr.get();364 365    Sym.Type = SymbolEntRef.getSymbolType();366    Sym.StorageClass = SymbolEntRef.getStorageClass();367    Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();368 369    if (Sym.NumberOfAuxEntries) {370      switch (Sym.StorageClass) {371      case XCOFF::C_FILE:372        if (Error E = dumpFileAuxSym(Sym, SymbolEntRef))373          return E;374        break;375      case XCOFF::C_STAT:376        if (Error E = dumpStatAuxSym(Sym, SymbolEntRef))377          return E;378        break;379      case XCOFF::C_EXT:380      case XCOFF::C_WEAKEXT:381      case XCOFF::C_HIDEXT:382        if (Error E = dumpAuxSyms(Sym, SymbolEntRef))383          return E;384        break;385      case XCOFF::C_BLOCK:386      case XCOFF::C_FCN:387        if (Error E = dumpBlockAuxSym(Sym, SymbolEntRef))388          return E;389        break;390      case XCOFF::C_DWARF:391        if (Error E = dumpDwarfAuxSym(Sym, SymbolEntRef))392          return E;393        break;394      default:395        break;396      }397    }398 399    Symbols.push_back(std::move(Sym));400  }401 402  return Error::success();403}404 405Error xcoff2yaml(raw_ostream &Out, const object::XCOFFObjectFile &Obj) {406  XCOFFDumper Dumper(Obj);407 408  if (Error E = Dumper.dump())409    return E;410 411  yaml::Output Yout(Out);412  Yout << Dumper.getYAMLObj();413 414  return Error::success();415}416