blob: 8ad3021a034287975f69d0aca1ef1d0eebec3833 [file] [log] [blame]
//===- XCOFFReader.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "XCOFFReader.h"
namespace llvm {
namespace objcopy {
namespace xcoff {
using namespace object;
Error XCOFFReader::readSections(Object &Obj) const {
ArrayRef<XCOFFSectionHeader32> Sections = XCOFFObj.sections32();
for (const XCOFFSectionHeader32 &Sec : Sections) {
Section ReadSec;
// Section header.
ReadSec.SectionHeader = Sec;
DataRefImpl SectionDRI;
SectionDRI.p = reinterpret_cast<uintptr_t>(&Sec);
// Section data.
if (Sec.SectionSize) {
Expected<ArrayRef<uint8_t>> ContentsRef =
XCOFFObj.getSectionContents(SectionDRI);
if (!ContentsRef)
return ContentsRef.takeError();
ReadSec.Contents = ContentsRef.get();
}
// Relocations.
if (Sec.NumberOfRelocations) {
auto Relocations =
XCOFFObj.relocations<XCOFFSectionHeader32, XCOFFRelocation32>(Sec);
if (!Relocations)
return Relocations.takeError();
for (const XCOFFRelocation32 &Rel : Relocations.get())
ReadSec.Relocations.push_back(Rel);
}
Obj.Sections.push_back(std::move(ReadSec));
}
return Error::success();
}
Error XCOFFReader::readSymbols(Object &Obj) const {
std::vector<Symbol> Symbols;
Symbols.reserve(XCOFFObj.getNumberOfSymbolTableEntries());
for (SymbolRef Sym : XCOFFObj.symbols()) {
Symbol ReadSym;
DataRefImpl SymbolDRI = Sym.getRawDataRefImpl();
XCOFFSymbolRef SymbolEntRef = XCOFFObj.toSymbolRef(SymbolDRI);
ReadSym.Sym = *SymbolEntRef.getSymbol32();
// Auxiliary entries.
if (SymbolEntRef.getNumberOfAuxEntries()) {
const char *Start = reinterpret_cast<const char *>(
SymbolDRI.p + XCOFF::SymbolTableEntrySize);
Expected<StringRef> RawAuxEntriesOrError = XCOFFObj.getRawData(
Start,
XCOFF::SymbolTableEntrySize * SymbolEntRef.getNumberOfAuxEntries(),
StringRef("symbol"));
if (!RawAuxEntriesOrError)
return RawAuxEntriesOrError.takeError();
ReadSym.AuxSymbolEntries = RawAuxEntriesOrError.get();
}
Obj.Symbols.push_back(std::move(ReadSym));
}
return Error::success();
}
Expected<std::unique_ptr<Object>> XCOFFReader::create() const {
auto Obj = std::make_unique<Object>();
// Only 32-bit supported now.
if (XCOFFObj.is64Bit())
return createStringError(object_error::invalid_file_type,
"64-bit XCOFF is not supported yet");
// Read the file header.
Obj->FileHeader = *XCOFFObj.fileHeader32();
// Read the optional header.
if (XCOFFObj.getOptionalHeaderSize())
Obj->OptionalFileHeader = *XCOFFObj.auxiliaryHeader32();
// Read each section.
Obj->Sections.reserve(XCOFFObj.getNumberOfSections());
if (Error E = readSections(*Obj))
return std::move(E);
// Read each symbol.
Obj->Symbols.reserve(XCOFFObj.getRawNumberOfSymbolTableEntries32());
if (Error E = readSymbols(*Obj))
return std::move(E);
// String table.
Obj->StringTable = XCOFFObj.getStringTable();
return std::move(Obj);
}
} // end namespace xcoff
} // end namespace objcopy
} // end namespace llvm