aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/XCOFFObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Object/XCOFFObjectFile.cpp')
-rw-r--r--llvm/lib/Object/XCOFFObjectFile.cpp112
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>>