xref: /freebsd/contrib/llvm-project/llvm/lib/ObjCopy/XCOFF/XCOFFReader.cpp (revision 9c77fb6aaa366cbabc80ee1b834bcfe4df135491)
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       llvm::append_range(ReadSec.Relocations, Relocations.get());
42     }
43 
44     Obj.Sections.push_back(std::move(ReadSec));
45   }
46   return Error::success();
47 }
48 
49 Error XCOFFReader::readSymbols(Object &Obj) const {
50   std::vector<Symbol> Symbols;
51   Symbols.reserve(XCOFFObj.getNumberOfSymbolTableEntries());
52   for (SymbolRef Sym : XCOFFObj.symbols()) {
53     Symbol ReadSym;
54     DataRefImpl SymbolDRI = Sym.getRawDataRefImpl();
55     XCOFFSymbolRef SymbolEntRef = XCOFFObj.toSymbolRef(SymbolDRI);
56     ReadSym.Sym = *SymbolEntRef.getSymbol32();
57     // Auxiliary entries.
58     if (SymbolEntRef.getNumberOfAuxEntries()) {
59       const char *Start = reinterpret_cast<const char *>(
60           SymbolDRI.p + XCOFF::SymbolTableEntrySize);
61       Expected<StringRef> RawAuxEntriesOrError = XCOFFObj.getRawData(
62           Start,
63           XCOFF::SymbolTableEntrySize * SymbolEntRef.getNumberOfAuxEntries(),
64           StringRef("symbol"));
65       if (!RawAuxEntriesOrError)
66         return RawAuxEntriesOrError.takeError();
67       ReadSym.AuxSymbolEntries = RawAuxEntriesOrError.get();
68     }
69     Obj.Symbols.push_back(std::move(ReadSym));
70   }
71   return Error::success();
72 }
73 
74 Expected<std::unique_ptr<Object>> XCOFFReader::create() const {
75   auto Obj = std::make_unique<Object>();
76   // Only 32-bit supported now.
77   if (XCOFFObj.is64Bit())
78     return createStringError(object_error::invalid_file_type,
79                              "64-bit XCOFF is not supported yet");
80   // Read the file header.
81   Obj->FileHeader = *XCOFFObj.fileHeader32();
82   // Read the optional header.
83   if (XCOFFObj.getOptionalHeaderSize())
84     Obj->OptionalFileHeader = *XCOFFObj.auxiliaryHeader32();
85   // Read each section.
86   Obj->Sections.reserve(XCOFFObj.getNumberOfSections());
87   if (Error E = readSections(*Obj))
88     return std::move(E);
89   // Read each symbol.
90   Obj->Symbols.reserve(XCOFFObj.getRawNumberOfSymbolTableEntries32());
91   if (Error E = readSymbols(*Obj))
92     return std::move(E);
93   // String table.
94   Obj->StringTable = XCOFFObj.getStringTable();
95   return std::move(Obj);
96 }
97 
98 } // end namespace xcoff
99 } // end namespace objcopy
100 } // end namespace llvm
101