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
11namespace llvm {
12namespace objcopy {
13namespace xcoff {
14
15using namespace object;
16
17Error 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(Sec: 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(C&: ReadSec.Relocations, R&: Relocations.get());
42 }
43
44 Obj.Sections.push_back(x: std::move(ReadSec));
45 }
46 return Error::success();
47}
48
49Error XCOFFReader::readSymbols(Object &Obj) const {
50 std::vector<Symbol> Symbols;
51 Symbols.reserve(n: XCOFFObj.getNumberOfSymbolTableEntries());
52 for (SymbolRef Sym : XCOFFObj.symbols()) {
53 Symbol ReadSym;
54 DataRefImpl SymbolDRI = Sym.getRawDataRefImpl();
55 XCOFFSymbolRef SymbolEntRef = XCOFFObj.toSymbolRef(Ref: 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 Size: XCOFF::SymbolTableEntrySize * SymbolEntRef.getNumberOfAuxEntries(),
64 Name: StringRef("symbol"));
65 if (!RawAuxEntriesOrError)
66 return RawAuxEntriesOrError.takeError();
67 ReadSym.AuxSymbolEntries = RawAuxEntriesOrError.get();
68 }
69 Obj.Symbols.push_back(x: std::move(ReadSym));
70 }
71 return Error::success();
72}
73
74Expected<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(EC: object_error::invalid_file_type,
79 S: "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(n: XCOFFObj.getNumberOfSections());
87 if (Error E = readSections(Obj&: *Obj))
88 return std::move(E);
89 // Read each symbol.
90 Obj->Symbols.reserve(n: XCOFFObj.getRawNumberOfSymbolTableEntries32());
91 if (Error E = readSymbols(Obj&: *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