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