diff options
Diffstat (limited to 'llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/XCOFFObjectFile.cpp | 112 |
1 files changed, 83 insertions, 29 deletions
diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index 2903251..e740855 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -22,6 +22,10 @@ namespace llvm { namespace object { +enum { XCOFF32FileHeaderSize = 20 }; +static_assert(sizeof(XCOFFFileHeader) == XCOFF32FileHeaderSize, + "Wrong size for XCOFF file header."); + // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. // Returns unexpected_eof on error. template <typename T> @@ -35,6 +39,40 @@ static std::error_code getObject(const T *&Obj, MemoryBufferRef M, return std::error_code(); } +template <typename T> static const T *viewAs(uintptr_t in) { + return reinterpret_cast<const T *>(in); +} + +const XCOFFSectionHeader *XCOFFObjectFile::toSection(DataRefImpl Ref) const { + auto Sec = viewAs<XCOFFSectionHeader>(Ref.p); +#ifndef NDEBUG + if (Sec < SectionHdrTablePtr || + Sec >= (SectionHdrTablePtr + getNumberOfSections())) + report_fatal_error("Section header outside of section header table."); + + uintptr_t Offset = uintptr_t(Sec) - uintptr_t(SectionHdrTablePtr); + if (Offset % getSectionHeaderSize() != 0) + report_fatal_error( + "Section header pointer does not point to a valid section header."); +#endif + return Sec; +} + +// The next 2 functions are not exactly necessary yet, but they are useful to +// abstract over the size difference between XCOFF32 and XCOFF64 structure +// definitions. +size_t XCOFFObjectFile::getFileHeaderSize() const { + return sizeof(XCOFFFileHeader); +} + +size_t XCOFFObjectFile::getSectionHeaderSize() const { + return sizeof(XCOFFSectionHeader); +} + +uint16_t XCOFFObjectFile::getNumberOfSections() const { + return FileHdrPtr->NumberOfSections; +} + void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { llvm_unreachable("Not yet implemented!"); return; @@ -77,32 +115,32 @@ XCOFFObjectFile::getSymbolSection(DataRefImpl Symb) const { } void XCOFFObjectFile::moveSectionNext(DataRefImpl &Sec) const { - llvm_unreachable("Not yet implemented!"); - return; + const char *Ptr = reinterpret_cast<const char *>(Sec.p); + Sec.p = reinterpret_cast<uintptr_t>(Ptr + getSectionHeaderSize()); } std::error_code XCOFFObjectFile::getSectionName(DataRefImpl Sec, StringRef &Res) const { - llvm_unreachable("Not yet implemented!"); + const char *Name = toSection(Sec)->Name; + auto NulCharPtr = + static_cast<const char *>(memchr(Name, '\0', XCOFF::SectionNameSize)); + Res = NulCharPtr ? StringRef(Name, NulCharPtr - Name) + : StringRef(Name, XCOFF::SectionNameSize); return std::error_code(); } uint64_t XCOFFObjectFile::getSectionAddress(DataRefImpl Sec) const { - uint64_t Result = 0; - llvm_unreachable("Not yet implemented!"); - return Result; + return toSection(Sec)->VirtualAddress; } uint64_t XCOFFObjectFile::getSectionIndex(DataRefImpl Sec) const { - uint64_t Result = 0; - llvm_unreachable("Not yet implemented!"); - return Result; + // Section numbers in XCOFF are numbered beginning at 1. A section number of + // zero is used to indicate that a symbol is being imported or is undefined. + return toSection(Sec) - SectionHdrTablePtr + 1; } uint64_t XCOFFObjectFile::getSectionSize(DataRefImpl Sec) const { - uint64_t Result = 0; - llvm_unreachable("Not yet implemented!"); - return Result; + return toSection(Sec)->SectionSize; } std::error_code XCOFFObjectFile::getSectionContents(DataRefImpl Sec, @@ -124,21 +162,17 @@ bool XCOFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { } bool XCOFFObjectFile::isSectionText(DataRefImpl Sec) const { - bool Result = false; - llvm_unreachable("Not yet implemented!"); - return Result; + return toSection(Sec)->Flags & XCOFF::STYP_TEXT; } bool XCOFFObjectFile::isSectionData(DataRefImpl Sec) const { - bool Result = false; - llvm_unreachable("Not yet implemented!"); - return Result; + unsigned Flags = toSection(Sec)->Flags; + return Flags & (XCOFF::STYP_DATA | XCOFF::STYP_TDATA); } bool XCOFFObjectFile::isSectionBSS(DataRefImpl Sec) const { - bool Result = false; - llvm_unreachable("Not yet implemented!"); - return Result; + unsigned Flags = toSection(Sec)->Flags; + return Flags & (XCOFF::STYP_BSS | XCOFF::STYP_TBSS); } bool XCOFFObjectFile::isSectionVirtual(DataRefImpl Sec) const { @@ -202,13 +236,16 @@ basic_symbol_iterator XCOFFObjectFile::symbol_end() const { } section_iterator XCOFFObjectFile::section_begin() const { - llvm_unreachable("Not yet implemented!"); - return section_iterator(SectionRef()); + DataRefImpl DRI; + DRI.p = reinterpret_cast<uintptr_t>(SectionHdrTablePtr); + return section_iterator(SectionRef(DRI, this)); } section_iterator XCOFFObjectFile::section_end() const { - llvm_unreachable("Not yet implemented!"); - return section_iterator(SectionRef()); + DataRefImpl DRI; + DRI.p = + reinterpret_cast<uintptr_t>(SectionHdrTablePtr + getNumberOfSections()); + return section_iterator(SectionRef(DRI, this)); } uint8_t XCOFFObjectFile::getBytesInAddress() const { @@ -218,13 +255,13 @@ uint8_t XCOFFObjectFile::getBytesInAddress() const { } StringRef XCOFFObjectFile::getFileFormatName() const { - llvm_unreachable("Not yet implemented!"); - return ""; + assert(getFileHeaderSize() == XCOFF32FileHeaderSize); + return "aixcoff-rs6000"; } Triple::ArchType XCOFFObjectFile::getArch() const { - llvm_unreachable("Not yet implemented!"); - return Triple::UnknownArch; + assert(getFileHeaderSize() == XCOFF32FileHeaderSize); + return Triple::ppc; } SubtargetFeatures XCOFFObjectFile::getFeatures() const { @@ -238,6 +275,12 @@ bool XCOFFObjectFile::isRelocatableObject() const { return Result; } +Expected<uint64_t> XCOFFObjectFile::getStartAddress() const { + // TODO FIXME Should get from auxiliary_header->o_entry when support for the + // auxiliary_header is added. + return 0; +} + XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC) : ObjectFile(Binary::ID_XCOFF32, Object) { @@ -246,6 +289,17 @@ XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC) if ((EC = getObject(FileHdrPtr, Data, base() + CurPtr))) return; + + CurPtr += getFileHeaderSize(); + // TODO FIXME we don't have support for an optional header yet, so just skip + // past it. + CurPtr += FileHdrPtr->AuxHeaderSize; + + if (getNumberOfSections() != 0) { + if ((EC = getObject(SectionHdrTablePtr, Data, base() + CurPtr, + getNumberOfSections() * getSectionHeaderSize()))) + return; + } } Expected<std::unique_ptr<ObjectFile>> |