forked from OSchip/llvm-project
102 lines
3.4 KiB
C++
102 lines
3.4 KiB
C++
//===- 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
|