mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
[Object][XCOFF] Add an XCOFF dumper for llvm-readobj.
Patch adds support for dumping of file headers with llvm-readobj. XCOFF object files are added to test dumping a well formed file, and dumping both negative timestamps and negative symbol counts, both of which are allowed in the XCOFF definition. Differential Revision: https://reviews.llvm.org/D60878 llvm-svn: 359878
This commit is contained in:
parent
72f050c770
commit
b7773a156f
@ -71,7 +71,6 @@ private:
|
|||||||
|
|
||||||
const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
|
const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
|
||||||
|
|
||||||
uint16_t getNumberOfSections() const;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void moveSymbolNext(DataRefImpl &Symb) const override;
|
void moveSymbolNext(DataRefImpl &Symb) const override;
|
||||||
@ -122,6 +121,18 @@ public:
|
|||||||
XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
|
XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
|
||||||
|
|
||||||
const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
|
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
|
}; // XCOFFObjectFile
|
||||||
|
|
||||||
} // namespace object
|
} // namespace object
|
||||||
|
@ -69,10 +69,6 @@ size_t XCOFFObjectFile::getSectionHeaderSize() const {
|
|||||||
return sizeof(XCOFFSectionHeader);
|
return sizeof(XCOFFSectionHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t XCOFFObjectFile::getNumberOfSections() const {
|
|
||||||
return FileHdrPtr->NumberOfSections;
|
|
||||||
}
|
|
||||||
|
|
||||||
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
|
void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
|
||||||
llvm_unreachable("Not yet implemented!");
|
llvm_unreachable("Not yet implemented!");
|
||||||
return;
|
return;
|
||||||
@ -247,9 +243,9 @@ section_iterator XCOFFObjectFile::section_end() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t XCOFFObjectFile::getBytesInAddress() const {
|
uint8_t XCOFFObjectFile::getBytesInAddress() const {
|
||||||
uint8_t Result = 0;
|
// Only support 32-bit object files for now ...
|
||||||
llvm_unreachable("Not yet implemented!");
|
assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
|
||||||
return Result;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef XCOFFObjectFile::getFileFormatName() const {
|
StringRef XCOFFObjectFile::getFileFormatName() const {
|
||||||
@ -300,6 +296,37 @@ XCOFFObjectFile::XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>>
|
Expected<std::unique_ptr<ObjectFile>>
|
||||||
ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
|
ObjectFile::createXCOFFObjectFile(MemoryBufferRef Object) {
|
||||||
StringRef Data = Object.getBuffer();
|
StringRef Data = Object.getBuffer();
|
||||||
|
BIN
test/tools/llvm-readobj/Inputs/xcoff-basic-neg-sym-count.o
Normal file
BIN
test/tools/llvm-readobj/Inputs/xcoff-basic-neg-sym-count.o
Normal file
Binary file not shown.
BIN
test/tools/llvm-readobj/Inputs/xcoff-basic-neg-time.o
Normal file
BIN
test/tools/llvm-readobj/Inputs/xcoff-basic-neg-time.o
Normal file
Binary file not shown.
BIN
test/tools/llvm-readobj/Inputs/xcoff-basic.o
Normal file
BIN
test/tools/llvm-readobj/Inputs/xcoff-basic.o
Normal file
Binary file not shown.
66
test/tools/llvm-readobj/xcoff-basic.test
Normal file
66
test/tools/llvm-readobj/xcoff-basic.test
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# 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.
|
||||||
|
|
@ -22,6 +22,7 @@ add_llvm_tool(llvm-readobj
|
|||||||
WasmDumper.cpp
|
WasmDumper.cpp
|
||||||
Win64EHDumper.cpp
|
Win64EHDumper.cpp
|
||||||
WindowsResourceDumper.cpp
|
WindowsResourceDumper.cpp
|
||||||
|
XCOFFDumper.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_llvm_tool_symlink(llvm-readelf llvm-readobj)
|
add_llvm_tool_symlink(llvm-readelf llvm-readobj)
|
||||||
|
@ -133,6 +133,10 @@ std::error_code createWasmDumper(const object::ObjectFile *Obj,
|
|||||||
ScopedPrinter &Writer,
|
ScopedPrinter &Writer,
|
||||||
std::unique_ptr<ObjDumper> &Result);
|
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,
|
void dumpCOFFImportFile(const object::COFFImportFile *File,
|
||||||
ScopedPrinter &Writer);
|
ScopedPrinter &Writer);
|
||||||
|
|
||||||
|
121
tools/llvm-readobj/XCOFFDumper.cpp
Normal file
121
tools/llvm-readobj/XCOFFDumper.cpp
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
//===-- 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
|
@ -440,6 +440,8 @@ static std::error_code createDumper(const ObjectFile *Obj,
|
|||||||
return createMachODumper(Obj, Writer, Result);
|
return createMachODumper(Obj, Writer, Result);
|
||||||
if (Obj->isWasm())
|
if (Obj->isWasm())
|
||||||
return createWasmDumper(Obj, Writer, Result);
|
return createWasmDumper(Obj, Writer, Result);
|
||||||
|
if (Obj->isXCOFF())
|
||||||
|
return createXCOFFDumper(Obj, Writer, Result);
|
||||||
|
|
||||||
return readobj_error::unsupported_obj_file_format;
|
return readobj_error::unsupported_obj_file_format;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user