xref: /freebsd/contrib/llvm-project/llvm/lib/ObjCopy/XCOFF/XCOFFReader.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1 //===- XCOFFReader.cpp ----------------------------------------------------===//
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 "XCOFFReader.h"
10 
11 namespace llvm {
12 namespace objcopy {
13 namespace xcoff {
14 
15 using namespace object;
16 
17 Error XCOFFReader::readSections(Object &Obj) const {
18   ArrayRef<XCOFFSectionHeader32> Sections = XCOFFObj.sections32();
19   for (const XCOFFSectionHeader32 &Sec : Sections) {
20     Section ReadSec;
21     // Section header.
22     ReadSec.SectionHeader = Sec;
23     DataRefImpl SectionDRI;
24     SectionDRI.p = reinterpret_cast<uintptr_t>(&Sec);
25 
26     // Section data.
27     if (Sec.SectionSize) {
28       Expected<ArrayRef<uint8_t>> ContentsRef =
29           XCOFFObj.getSectionContents(SectionDRI);
30       if (!ContentsRef)
31         return ContentsRef.takeError();
32       ReadSec.Contents = ContentsRef.get();
33     }
34 
35     // Relocations.
36     if (Sec.NumberOfRelocations) {
37       auto Relocations =
38           XCOFFObj.relocations<XCOFFSectionHeader32, XCOFFRelocation32>(Sec);
39       if (!Relocations)
40         return Relocations.takeError();
41       for (const XCOFFRelocation32 &Rel : Relocations.get())
42         ReadSec.Relocations.push_back(Rel);
43     }
44 
45     Obj.Sections.push_back(std::move(ReadSec));
46   }
47   return Error::success();
48 }
49 
50 Error XCOFFReader::readSymbols(Object &Obj) const {
51   std::vector<Symbol> Symbols;
52   Symbols.reserve(XCOFFObj.getNumberOfSymbolTableEntries());
53   for (SymbolRef Sym : XCOFFObj.symbols()) {
54     Symbol ReadSym;
55     DataRefImpl SymbolDRI = Sym.getRawDataRefImpl();
56     XCOFFSymbolRef SymbolEntRef = XCOFFObj.toSymbolRef(SymbolDRI);
57     ReadSym.Sym = *SymbolEntRef.getSymbol32();
58     // Auxiliary entries.
59     if (SymbolEntRef.getNumberOfAuxEntries()) {
60       const char *Start = reinterpret_cast<const char *>(
61           SymbolDRI.p + XCOFF::SymbolTableEntrySize);
62       Expected<StringRef> RawAuxEntriesOrError = XCOFFObj.getRawData(
63           Start,
64           XCOFF::SymbolTableEntrySize * SymbolEntRef.getNumberOfAuxEntries(),
65           StringRef("symbol"));
66       if (!RawAuxEntriesOrError)
67         return RawAuxEntriesOrError.takeError();
68       ReadSym.AuxSymbolEntries = RawAuxEntriesOrError.get();
69     }
70     Obj.Symbols.push_back(std::move(ReadSym));
71   }
72   return Error::success();
73 }
74 
75 Expected<std::unique_ptr<Object>> XCOFFReader::create() const {
76   auto Obj = std::make_unique<Object>();
77   // Only 32-bit supported now.
78   if (XCOFFObj.is64Bit())
79     return createStringError(object_error::invalid_file_type,
80                              "64-bit XCOFF is not supported yet");
81   // Read the file header.
82   Obj->FileHeader = *XCOFFObj.fileHeader32();
83   // Read the optional header.
84   if (XCOFFObj.getOptionalHeaderSize())
85     Obj->OptionalFileHeader = *XCOFFObj.auxiliaryHeader32();
86   // Read each section.
87   Obj->Sections.reserve(XCOFFObj.getNumberOfSections());
88   if (Error E = readSections(*Obj))
89     return std::move(E);
90   // Read each symbol.
91   Obj->Symbols.reserve(XCOFFObj.getRawNumberOfSymbolTableEntries32());
92   if (Error E = readSymbols(*Obj))
93     return std::move(E);
94   // String table.
95   Obj->StringTable = XCOFFObj.getStringTable();
96   return std::move(Obj);
97 }
98 
99 } // end namespace xcoff
100 } // end namespace objcopy
101 } // end namespace llvm
102