[RISCV] Eliminate dead li after emitting VSETVLIs (#65934)
[llvm-project.git] / llvm / tools / obj2yaml / xcoff2yaml.cpp
blobf7c2bae74798951586d82b14d718efc3f2e5ce90
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 //===----------------------------------------------------------------------===//
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"
15 using namespace llvm;
16 using namespace llvm::object;
17 namespace {
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);
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 dumpCscetAuxSym(XCOFFYAML::Symbol &Sym,
41 const object::XCOFFCsectAuxRef &AuxEntPtr);
43 public:
44 XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {}
45 Error dump();
46 XCOFFYAML::Object &getYAMLObj() { return YAMLObj; }
48 template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress) {
49 Obj.checkSymbolEntryPointer(AuxAddress);
50 return reinterpret_cast<const T *>(AuxAddress);
53 } // namespace
55 Error XCOFFDumper::dump() {
56 dumpHeader();
57 if (Error E = dumpSections())
58 return E;
59 return dumpSymbols();
62 void 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();
76 Error XCOFFDumper::dumpSections() {
77 if (Obj.is64Bit())
78 return dumpSections<XCOFFSectionHeader64, XCOFFRelocation64>(
79 Obj.sections64());
80 return dumpSections<XCOFFSectionHeader32, XCOFFRelocation32>(
81 Obj.sections32());
84 template <typename Shdr, typename Reloc>
85 Error 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;
99 // Dump section data.
100 if (S.FileOffsetToRawData) {
101 DataRefImpl SectionDRI;
102 SectionDRI.p = reinterpret_cast<uintptr_t>(&S);
103 Expected<ArrayRef<uint8_t>> SecDataRefOrErr =
104 Obj.getSectionContents(SectionDRI);
105 if (!SecDataRefOrErr)
106 return SecDataRefOrErr.takeError();
107 YamlSec.SectionData = SecDataRefOrErr.get();
110 // Dump relocations.
111 if (S.NumberOfRelocations) {
112 auto RelRefOrErr = Obj.relocations<Shdr, Reloc>(S);
113 if (!RelRefOrErr)
114 return RelRefOrErr.takeError();
115 for (const Reloc &R : RelRefOrErr.get()) {
116 XCOFFYAML::Relocation YamlRel;
117 YamlRel.Type = R.Type;
118 YamlRel.Info = R.Info;
119 YamlRel.SymbolIndex = R.SymbolIndex;
120 YamlRel.VirtualAddress = R.VirtualAddress;
121 YamlSec.Relocations.push_back(YamlRel);
124 YamlSections.push_back(YamlSec);
126 return Error::success();
129 Error XCOFFDumper::dumpFileAuxSym(XCOFFYAML::Symbol &Sym,
130 const XCOFFSymbolRef &SymbolEntRef) {
131 for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) {
132 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
133 SymbolEntRef.getEntryAddress(), I);
134 const XCOFFFileAuxEnt *FileAuxEntPtr =
135 getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
136 auto FileNameOrError = Obj.getCFileName(FileAuxEntPtr);
137 if (!FileNameOrError)
138 return FileNameOrError.takeError();
140 XCOFFYAML::FileAuxEnt FileAuxSym;
141 FileAuxSym.FileNameOrString = FileNameOrError.get();
142 FileAuxSym.FileStringType = FileAuxEntPtr->Type;
143 Sym.AuxEntries.push_back(
144 std::make_unique<XCOFFYAML::FileAuxEnt>(FileAuxSym));
146 return Error::success();
149 Error XCOFFDumper::dumpStatAuxSym(XCOFFYAML::Symbol &Sym,
150 const XCOFFSymbolRef &SymbolEntRef) {
151 if (Sym.NumberOfAuxEntries != 1) {
152 uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
153 return createError("failed to parse symbol \"" + Sym.SymbolName +
154 "\" with index of " + Twine(SymbolIndex) +
155 ": expected 1 aux symbol for C_STAT, while got " +
156 Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));
159 const XCOFFSectAuxEntForStat *AuxEntPtr =
160 getAuxEntPtr<XCOFFSectAuxEntForStat>(
161 XCOFFObjectFile::getAdvancedSymbolEntryAddress(
162 SymbolEntRef.getEntryAddress(), 1));
163 XCOFFYAML::SectAuxEntForStat StatAuxSym;
164 StatAuxSym.SectionLength = AuxEntPtr->SectionLength;
165 StatAuxSym.NumberOfLineNum = AuxEntPtr->NumberOfLineNum;
166 StatAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;
167 Sym.AuxEntries.push_back(
168 std::make_unique<XCOFFYAML::SectAuxEntForStat>(StatAuxSym));
169 return Error::success();
172 void XCOFFDumper::dumpFuncAuxSym(XCOFFYAML::Symbol &Sym,
173 const uintptr_t AuxAddress) {
174 XCOFFYAML::FunctionAuxEnt FunAuxSym;
176 if (Obj.is64Bit()) {
177 const XCOFFFunctionAuxEnt64 *AuxEntPtr =
178 getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
179 FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum;
180 FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;
181 FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;
182 } else {
183 const XCOFFFunctionAuxEnt32 *AuxEntPtr =
184 getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
185 FunAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl;
186 FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum;
187 FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;
188 FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;
191 Sym.AuxEntries.push_back(
192 std::make_unique<XCOFFYAML::FunctionAuxEnt>(FunAuxSym));
195 void XCOFFDumper::dumpExpAuxSym(XCOFFYAML::Symbol &Sym,
196 const uintptr_t AuxAddress) {
197 const XCOFFExceptionAuxEnt *AuxEntPtr =
198 getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
199 XCOFFYAML::ExcpetionAuxEnt ExceptAuxSym;
200 ExceptAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl;
201 ExceptAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;
202 ExceptAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;
203 Sym.AuxEntries.push_back(
204 std::make_unique<XCOFFYAML::ExcpetionAuxEnt>(ExceptAuxSym));
207 void XCOFFDumper::dumpCscetAuxSym(XCOFFYAML::Symbol &Sym,
208 const object::XCOFFCsectAuxRef &AuxEntPtr) {
209 XCOFFYAML::CsectAuxEnt CsectAuxSym;
210 CsectAuxSym.ParameterHashIndex = AuxEntPtr.getParameterHashIndex();
211 CsectAuxSym.TypeChkSectNum = AuxEntPtr.getTypeChkSectNum();
212 CsectAuxSym.SymbolAlignmentAndType = AuxEntPtr.getSymbolAlignmentAndType();
213 CsectAuxSym.StorageMappingClass = AuxEntPtr.getStorageMappingClass();
215 if (Obj.is64Bit()) {
216 CsectAuxSym.SectionOrLengthLo =
217 static_cast<uint32_t>(AuxEntPtr.getSectionOrLength64());
218 CsectAuxSym.SectionOrLengthHi =
219 static_cast<uint32_t>(AuxEntPtr.getSectionOrLength64() >> 32);
220 } else {
221 CsectAuxSym.SectionOrLength = AuxEntPtr.getSectionOrLength32();
222 CsectAuxSym.StabInfoIndex = AuxEntPtr.getStabInfoIndex32();
223 CsectAuxSym.StabSectNum = AuxEntPtr.getStabSectNum32();
226 Sym.AuxEntries.push_back(
227 std::make_unique<XCOFFYAML::CsectAuxEnt>(CsectAuxSym));
230 Error XCOFFDumper::dumpAuxSyms(XCOFFYAML::Symbol &Sym,
231 const XCOFFSymbolRef &SymbolEntRef) {
232 auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
233 if (!ErrOrCsectAuxRef)
234 return ErrOrCsectAuxRef.takeError();
235 XCOFFCsectAuxRef CsectAuxRef = ErrOrCsectAuxRef.get();
237 for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) {
239 if (I == Sym.NumberOfAuxEntries && !Obj.is64Bit()) {
240 dumpCscetAuxSym(Sym, CsectAuxRef);
241 return Error::success();
244 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
245 SymbolEntRef.getEntryAddress(), I);
247 if (Obj.is64Bit()) {
248 XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
249 if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
250 dumpCscetAuxSym(Sym, CsectAuxRef);
251 else if (Type == XCOFF::SymbolAuxType::AUX_FCN)
252 dumpFuncAuxSym(Sym, AuxAddress);
253 else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT)
254 dumpExpAuxSym(Sym, AuxAddress);
255 else {
256 uint32_t SymbolIndex =
257 Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
258 return createError("failed to parse symbol \"" + Sym.SymbolName +
259 "\" with index of " + Twine(SymbolIndex) +
260 ": invalid auxiliary symbol type: " +
261 Twine(static_cast<uint32_t>(Type)));
264 } else
265 dumpFuncAuxSym(Sym, AuxAddress);
268 return Error::success();
271 Error XCOFFDumper::dumpBlockAuxSym(XCOFFYAML::Symbol &Sym,
272 const XCOFFSymbolRef &SymbolEntRef) {
273 if (Sym.NumberOfAuxEntries != 1) {
274 uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
275 return createError(
276 "failed to parse symbol \"" + Sym.SymbolName + "\" with index of " +
277 Twine(SymbolIndex) +
278 ": expected 1 aux symbol for C_BLOCK or C_FCN, while got " +
279 Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));
282 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
283 SymbolEntRef.getEntryAddress(), 1);
284 XCOFFYAML::BlockAuxEnt BlockAuxSym;
286 if (Obj.is64Bit()) {
287 const XCOFFBlockAuxEnt64 *AuxEntPtr =
288 getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
289 BlockAuxSym.LineNum = AuxEntPtr->LineNum;
290 } else {
291 const XCOFFBlockAuxEnt32 *AuxEntPtr =
292 getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
293 BlockAuxSym.LineNumLo = AuxEntPtr->LineNumLo;
294 BlockAuxSym.LineNumHi = AuxEntPtr->LineNumHi;
297 Sym.AuxEntries.push_back(
298 std::make_unique<XCOFFYAML::BlockAuxEnt>(BlockAuxSym));
299 return Error::success();
302 Error XCOFFDumper::dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym,
303 const XCOFFSymbolRef &SymbolEntRef) {
304 if (Sym.NumberOfAuxEntries != 1) {
305 uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
306 return createError("failed to parse symbol \"" + Sym.SymbolName +
307 "\" with index of " + Twine(SymbolIndex) +
308 ": expected 1 aux symbol for C_DWARF, while got " +
309 Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));
312 uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
313 SymbolEntRef.getEntryAddress(), 1);
314 XCOFFYAML::SectAuxEntForDWARF DwarfAuxSym;
316 if (Obj.is64Bit()) {
317 const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
318 getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
319 DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion;
320 DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;
321 } else {
322 const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
323 getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
324 DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion;
325 DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;
328 Sym.AuxEntries.push_back(
329 std::make_unique<XCOFFYAML::SectAuxEntForDWARF>(DwarfAuxSym));
330 return Error::success();
333 Error XCOFFDumper::dumpSymbols() {
334 std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
336 for (const SymbolRef &S : Obj.symbols()) {
337 DataRefImpl SymbolDRI = S.getRawDataRefImpl();
338 const XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
339 XCOFFYAML::Symbol Sym;
341 Expected<StringRef> SymNameRefOrErr = Obj.getSymbolName(SymbolDRI);
342 if (!SymNameRefOrErr) {
343 return SymNameRefOrErr.takeError();
345 Sym.SymbolName = SymNameRefOrErr.get();
347 Sym.Value = SymbolEntRef.getValue();
349 Expected<StringRef> SectionNameRefOrErr =
350 Obj.getSymbolSectionName(SymbolEntRef);
351 if (!SectionNameRefOrErr)
352 return SectionNameRefOrErr.takeError();
354 Sym.SectionName = SectionNameRefOrErr.get();
356 Sym.Type = SymbolEntRef.getSymbolType();
357 Sym.StorageClass = SymbolEntRef.getStorageClass();
358 Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
360 if (Sym.NumberOfAuxEntries) {
361 switch (Sym.StorageClass) {
362 case XCOFF::C_FILE:
363 if (Error E = dumpFileAuxSym(Sym, SymbolEntRef))
364 return E;
365 break;
366 case XCOFF::C_STAT:
367 if (Error E = dumpStatAuxSym(Sym, SymbolEntRef))
368 return E;
369 break;
370 case XCOFF::C_EXT:
371 case XCOFF::C_WEAKEXT:
372 case XCOFF::C_HIDEXT:
373 if (Error E = dumpAuxSyms(Sym, SymbolEntRef))
374 return E;
375 break;
376 case XCOFF::C_BLOCK:
377 case XCOFF::C_FCN:
378 if (Error E = dumpBlockAuxSym(Sym, SymbolEntRef))
379 return E;
380 break;
381 case XCOFF::C_DWARF:
382 if (Error E = dumpDwarfAuxSym(Sym, SymbolEntRef))
383 return E;
384 break;
385 default:
386 break;
390 Symbols.push_back(std::move(Sym));
393 return Error::success();
396 Error xcoff2yaml(raw_ostream &Out, const object::XCOFFObjectFile &Obj) {
397 XCOFFDumper Dumper(Obj);
399 if (Error E = Dumper.dump())
400 return E;
402 yaml::Output Yout(Out);
403 Yout << Dumper.getYAMLObj();
405 return Error::success();