const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
- uint16_t getNumberOfSections() const;
public:
void moveSymbolNext(DataRefImpl &Symb) const override;
XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
+
+ uint16_t getMagic() const;
+ uint16_t getNumberOfSections() const;
+ int32_t getTimeStamp() const;
+ uint32_t getSymbolTableOffset() const;
+
+ // Note that this value is signed and might return a negative value. Negative
+ // values are reserved for future use.
+ int32_t getNumberOfSymbolTableEntries() const;
+
+ uint16_t getOptionalHeaderSize() const;
+ uint16_t getFlags() const;
}; // XCOFFObjectFile
} // namespace object
return sizeof(XCOFFSectionHeader);
}
-uint16_t XCOFFObjectFile::getNumberOfSections() const {
- return FileHdrPtr->NumberOfSections;
-}
-
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
llvm_unreachable("Not yet implemented!");
return;
}
uint8_t XCOFFObjectFile::getBytesInAddress() const {
- uint8_t Result = 0;
- llvm_unreachable("Not yet implemented!");
- return Result;
+ // Only support 32-bit object files for now ...
+ assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
+ return 4;
}
StringRef XCOFFObjectFile::getFileFormatName() const {
}
}
+uint16_t XCOFFObjectFile::getMagic() const {
+ return FileHdrPtr->Magic;
+}
+
+uint16_t XCOFFObjectFile::getNumberOfSections() const {
+ return FileHdrPtr->NumberOfSections;
+}
+
+int32_t XCOFFObjectFile::getTimeStamp() const {
+ return FileHdrPtr->TimeStamp;
+}
+
+uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
+ return FileHdrPtr->SymbolTableOffset;
+}
+
+int32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
+ // As far as symbol table size is concerned, if this field is negative it is
+ // to be treated as a 0. However since this field is also used for printing we
+ // don't want to truncate any negative values.
+ return FileHdrPtr->NumberOfSymTableEntries;
+}
+
+uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
+ return FileHdrPtr->AuxHeaderSize;
+}
+
+uint16_t XCOFFObjectFile::getFlags() const {
+ return FileHdrPtr->Flags;
+}
+
Expected<std::unique_ptr<ObjectFile>>
ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
StringRef Data = Object.getBuffer();
--- /dev/null
+# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic.o | \
+# RUN: FileCheck --check-prefix=FILEHEADER %s
+
+# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-time.o | \
+# RUN: FileCheck --check-prefix=NEGTIME %s
+
+# RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-sym-count.o | \
+# RUN: FileCheck --check-prefix=NEGSYMCOUNT %s
+
+# FILEHEADER: File: {{.*}}xcoff-basic.o
+# FILEHEADER-NEXT: Format: aixcoff-rs6000
+# FILEHEADER-NEXT: Arch: powerpc
+# FILEHEADER-NEXT: AddressSize: 32bit
+# FILEHEADER-NEXT: FileHeader {
+# FILEHEADER-NEXT: Magic: 0x1DF
+# FILEHEADER-NEXT: NumberOfSections: 6
+# FILEHEADER-NEXT: TimeStamp: 2019-03-12T14:04:43Z (0x5C87BC7B)
+# FILEHEADER-NEXT: SymbolTableOffset: 0x52E
+# FILEHEADER-NEXT: SymbolTableEntries: 120
+# FILEHEADER-NEXT: OptionalHeaderSize: 0x1C
+# FILEHEADER-NEXT: Flags: 0x0
+# FILEHEADER-NEXT: }
+
+# NEGTIME: File: {{.*}}xcoff-basic-neg-time.o
+# NEGTIME-NEXT: Format: aixcoff-rs6000
+# NEGTIME-NEXT: Arch: powerpc
+# NEGTIME-NEXT: AddressSize: 32bit
+# NEGTIME-NEXT: FileHeader {
+# NEGTIME-NEXT: Magic: 0x1DF
+# NEGTIME-NEXT: NumberOfSections: 6
+# NEGTIME-NEXT: TimeStamp: Reserved Value (0xDC87BC7B)
+# NEGTIME-NEXT: SymbolTableOffset: 0x52E
+# NEGTIME-NEXT: SymbolTableEntries: 120
+# NEGTIME-NEXT: OptionalHeaderSize: 0x1C
+# NEGTIME-NEXT: Flags: 0x0
+# NEGTIME-NEXT: }
+
+# NEGSYMCOUNT: File: {{.*}}xcoff-basic-neg-sym-count.o
+# NEGSYMCOUNT-NEXT: Format: aixcoff-rs6000
+# NEGSYMCOUNT-NEXT: Arch: powerpc
+# NEGSYMCOUNT-NEXT: AddressSize: 32bit
+# NEGSYMCOUNT-NEXT: FileHeader {
+# NEGSYMCOUNT-NEXT: Magic: 0x1DF
+# NEGSYMCOUNT-NEXT: NumberOfSections: 5
+# NEGSYMCOUNT-NEXT: TimeStamp: 2019-03-12T14:04:43Z (0x5C87BC7B)
+# NEGSYMCOUNT-NEXT: SymbolTableOffset: 0x0
+# NEGSYMCOUNT-NEXT: SymbolTableEntries: Reserved Value (0x80000000)
+# NEGSYMCOUNT-NEXT: OptionalHeaderSize: 0x1C
+# NEGSYMCOUNT-NEXT: Flags: 0xD
+# NEGSYMCOUNT-NEXT: }
+
+# xcoff-basic.o was compiled with `xlc -qtls -O3 -g -c xcoff-basic.c`
+# from the following source:
+# int a = 55;
+# int b;
+# __thread int j = 55;
+# __thread double d;
+# int A() { return a; }
+# int B() { return b; }
+# int J() { return j; }
+# double D() { return d; }
+#
+# xcoff-basic-neg-time.o was manually edited to include a negative time stamp.
+# xcoff-basic-neg-sym-count.o was stripped using the 'strip' utility, and
+# manually edited to have a negative symbol table entry count.
+
WasmDumper.cpp
Win64EHDumper.cpp
WindowsResourceDumper.cpp
+ XCOFFDumper.cpp
)
add_llvm_tool_symlink(llvm-readelf llvm-readobj)
ScopedPrinter &Writer,
std::unique_ptr<ObjDumper> &Result);
+std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
+ ScopedPrinter &Writer,
+ std::unique_ptr<ObjDumper> &Result);
+
void dumpCOFFImportFile(const object::COFFImportFile *File,
ScopedPrinter &Writer);
--- /dev/null
+//===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements an XCOFF specific dumper for llvm-readobj.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "ObjDumper.h"
+#include "llvm-readobj.h"
+#include "llvm/Object/XCOFFObjectFile.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace object;
+
+namespace {
+
+class XCOFFDumper : public ObjDumper {
+public:
+ XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
+ : ObjDumper(Writer), Obj(Obj) {}
+
+ void printFileHeaders() override;
+ void printSectionHeaders() override;
+ void printRelocations() override;
+ void printSymbols() override;
+ void printDynamicSymbols() override;
+ void printUnwindInfo() override;
+ void printStackMap() const override;
+ void printNeededLibraries() override;
+
+private:
+ const XCOFFObjectFile &Obj;
+};
+} // anonymous namespace
+
+void XCOFFDumper::printFileHeaders() {
+ DictScope DS(W, "FileHeader");
+ W.printHex("Magic", Obj.getMagic());
+ W.printNumber("NumberOfSections", Obj.getNumberOfSections());
+
+ // Negative timestamp values are reserved for future use.
+ int32_t TimeStamp = Obj.getTimeStamp();
+ if (TimeStamp > 0) {
+ // This handling of the time stamp assumes that the host system's time_t is
+ // compatible with AIX time_t. If a platform is not compatible, the lit
+ // tests will let us know.
+ time_t TimeDate = TimeStamp;
+
+ char FormattedTime[21] = {};
+ size_t BytesWritten =
+ strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
+ if (BytesWritten)
+ W.printHex("TimeStamp", FormattedTime, TimeStamp);
+ else
+ W.printHex("Timestamp", TimeStamp);
+ } else {
+ W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
+ TimeStamp);
+ }
+
+ W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset());
+ int32_t SymTabEntries = Obj.getNumberOfSymbolTableEntries();
+ if (SymTabEntries >= 0)
+ W.printNumber("SymbolTableEntries", SymTabEntries);
+ else
+ W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
+
+ W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
+ W.printHex("Flags", Obj.getFlags());
+
+ // TODO FIXME Add support for the auxiliary header (if any) once
+ // XCOFFObjectFile has the necessary support.
+}
+
+void XCOFFDumper::printSectionHeaders() {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+void XCOFFDumper::printRelocations() {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+void XCOFFDumper::printSymbols() {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+void XCOFFDumper::printDynamicSymbols() {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+void XCOFFDumper::printUnwindInfo() {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+void XCOFFDumper::printStackMap() const {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+void XCOFFDumper::printNeededLibraries() {
+ llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+}
+
+namespace llvm {
+std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
+ ScopedPrinter &Writer,
+ std::unique_ptr<ObjDumper> &Result) {
+ const XCOFFObjectFile *XObj = dyn_cast<XCOFFObjectFile>(Obj);
+ if (!XObj)
+ return readobj_error::unsupported_obj_file_format;
+
+ Result.reset(new XCOFFDumper(*XObj, Writer));
+ return readobj_error::success;
+}
+} // namespace llvm
return createMachODumper(Obj, Writer, Result);
if (Obj->isWasm())
return createWasmDumper(Obj, Writer, Result);
+ if (Obj->isXCOFF())
+ return createXCOFFDumper(Obj, Writer, Result);
return readobj_error::unsupported_obj_file_format;
}