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(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
50Error 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
75Expected<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