//===- 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 Sections = XCOFFObj.sections32(); for (const XCOFFSectionHeader32 &Sec : Sections) { Section ReadSec; // Section header. ReadSec.SectionHeader = Sec; DataRefImpl SectionDRI; SectionDRI.p = reinterpret_cast(&Sec); // Section data. if (Sec.SectionSize) { Expected> ContentsRef = XCOFFObj.getSectionContents(SectionDRI); if (!ContentsRef) return ContentsRef.takeError(); ReadSec.Contents = ContentsRef.get(); } // Relocations. if (Sec.NumberOfRelocations) { auto Relocations = XCOFFObj.relocations(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 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( SymbolDRI.p + XCOFF::SymbolTableEntrySize); Expected 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> XCOFFReader::create() const { auto Obj = std::make_unique(); // 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