xref: /openbsd-src/gnu/llvm/llvm/tools/obj2yaml/xcoff2yaml.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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()35 Error XCOFFDumper::dump() {
36   dumpHeader();
37   if (Error E = dumpSections())
38     return E;
39   return dumpSymbols();
40 }
41 
dumpHeader()42 void 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()56 Error 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)65 Error 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()109 Error 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)142 Error 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