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-exception 6 // 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 15 using namespace llvm; 16 using namespace llvm::object; 17 namespace { 18 19 class 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 public: XCOFFDumper(const object::XCOFFObjectFile & obj)29 XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {} 30 Error dump(); getYAMLObj()31 XCOFFYAML::Object &getYAMLObj() { return YAMLObj; } 32 }; 33 } // namespace 34 dump()35Error XCOFFDumper::dump() { 36 dumpHeader(); 37 if (Error E = dumpSections()) 38 return E; 39 return dumpSymbols(); 40 } 41 dumpHeader()42void XCOFFDumper::dumpHeader() { 43 YAMLObj.Header.Magic = Obj.getMagic(); 44 YAMLObj.Header.NumberOfSections = Obj.getNumberOfSections(); 45 YAMLObj.Header.TimeStamp = Obj.getTimeStamp(); 46 YAMLObj.Header.SymbolTableOffset = Obj.is64Bit() 47 ? Obj.getSymbolTableOffset64() 48 : Obj.getSymbolTableOffset32(); 49 YAMLObj.Header.NumberOfSymTableEntries = 50 Obj.is64Bit() ? Obj.getNumberOfSymbolTableEntries64() 51 : Obj.getRawNumberOfSymbolTableEntries32(); 52 YAMLObj.Header.AuxHeaderSize = Obj.getOptionalHeaderSize(); 53 YAMLObj.Header.Flags = Obj.getFlags(); 54 } 55 dumpSections()56Error XCOFFDumper::dumpSections() { 57 if (Obj.is64Bit()) 58 return dumpSections<XCOFFSectionHeader64, XCOFFRelocation64>( 59 Obj.sections64()); 60 return dumpSections<XCOFFSectionHeader32, XCOFFRelocation32>( 61 Obj.sections32()); 62 } 63 64 template <typename Shdr, typename Reloc> dumpSections(ArrayRef<Shdr> Sections)65Error XCOFFDumper::dumpSections(ArrayRef<Shdr> Sections) { 66 std::vector<XCOFFYAML::Section> &YamlSections = YAMLObj.Sections; 67 for (const Shdr &S : Sections) { 68 XCOFFYAML::Section YamlSec; 69 YamlSec.SectionName = S.getName(); 70 YamlSec.Address = S.PhysicalAddress; 71 YamlSec.Size = S.SectionSize; 72 YamlSec.NumberOfRelocations = S.NumberOfRelocations; 73 YamlSec.NumberOfLineNumbers = S.NumberOfLineNumbers; 74 YamlSec.FileOffsetToData = S.FileOffsetToRawData; 75 YamlSec.FileOffsetToRelocations = S.FileOffsetToRelocationInfo; 76 YamlSec.FileOffsetToLineNumbers = S.FileOffsetToLineNumberInfo; 77 YamlSec.Flags = S.Flags; 78 79 // Dump section data. 80 if (S.FileOffsetToRawData) { 81 DataRefImpl SectionDRI; 82 SectionDRI.p = reinterpret_cast<uintptr_t>(&S); 83 Expected<ArrayRef<uint8_t>> SecDataRefOrErr = 84 Obj.getSectionContents(SectionDRI); 85 if (!SecDataRefOrErr) 86 return SecDataRefOrErr.takeError(); 87 YamlSec.SectionData = SecDataRefOrErr.get(); 88 } 89 90 // Dump relocations. 91 if (S.NumberOfRelocations) { 92 auto RelRefOrErr = Obj.relocations<Shdr, Reloc>(S); 93 if (!RelRefOrErr) 94 return RelRefOrErr.takeError(); 95 for (const Reloc &R : RelRefOrErr.get()) { 96 XCOFFYAML::Relocation YamlRel; 97 YamlRel.Type = R.Type; 98 YamlRel.Info = R.Info; 99 YamlRel.SymbolIndex = R.SymbolIndex; 100 YamlRel.VirtualAddress = R.VirtualAddress; 101 YamlSec.Relocations.push_back(YamlRel); 102 } 103 } 104 YamlSections.push_back(YamlSec); 105 } 106 return Error::success(); 107 } 108 dumpSymbols()109Error XCOFFDumper::dumpSymbols() { 110 std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols; 111 112 for (const SymbolRef &S : Obj.symbols()) { 113 DataRefImpl SymbolDRI = S.getRawDataRefImpl(); 114 const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI); 115 XCOFFYAML::Symbol Sym; 116 117 Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI); 118 if (!SymNameRefOrErr) { 119 return SymNameRefOrErr.takeError(); 120 } 121 Sym.SymbolName = SymNameRefOrErr.get(); 122 123 Sym.Value = SymbolEntRef.getValue(); 124 125 Expected<StringRef> SectionNameRefOrErr = 126 Obj.getSymbolSectionName(SymbolEntRef); 127 if (!SectionNameRefOrErr) 128 return SectionNameRefOrErr.takeError(); 129 130 Sym.SectionName = SectionNameRefOrErr.get(); 131 132 Sym.Type = SymbolEntRef.getSymbolType(); 133 Sym.StorageClass = SymbolEntRef.getStorageClass(); 134 Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries(); 135 136 Symbols.push_back(std::move(Sym)); 137 } 138 139 return Error::success(); 140 } 141 xcoff2yaml(raw_ostream & Out,const object::XCOFFObjectFile & Obj)142Error xcoff2yaml(raw_ostream &Out, const object::XCOFFObjectFile &Obj) { 143 XCOFFDumper Dumper(Obj); 144 145 if (Error E = Dumper.dump()) 146 return E; 147 148 yaml::Output Yout(Out); 149 Yout << Dumper.getYAMLObj(); 150 151 return Error::success(); 152 } 153