| //===- 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 |