llvm.org GIT mirror llvm / c0bc443
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359878 91177308-0d34-0410-b5e6-96231b3b80d8 Sean Fertile 1 year, 29 days ago
10 changed file(s) with 240 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
7070
7171 const XCOFFSectionHeader *toSection(DataRefImpl Ref) const;
7272
73 uint16_t getNumberOfSections() const;
7473
7574 public:
7675 void moveSymbolNext(DataRefImpl &Symb) const override;
121120 XCOFFObjectFile(MemoryBufferRef Object, std::error_code &EC);
122121
123122 const XCOFFFileHeader *getFileHeader() const { return FileHdrPtr; }
123
124 uint16_t getMagic() const;
125 uint16_t getNumberOfSections() const;
126 int32_t getTimeStamp() const;
127 uint32_t getSymbolTableOffset() const;
128
129 // Note that this value is signed and might return a negative value. Negative
130 // values are reserved for future use.
131 int32_t getNumberOfSymbolTableEntries() const;
132
133 uint16_t getOptionalHeaderSize() const;
134 uint16_t getFlags() const;
124135 }; // XCOFFObjectFile
125136
126137 } // namespace object
6868 return sizeof(XCOFFSectionHeader);
6969 }
7070
71 uint16_t XCOFFObjectFile::getNumberOfSections() const {
72 return FileHdrPtr->NumberOfSections;
73 }
74
7571 void XCOFFObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
7672 llvm_unreachable("Not yet implemented!");
7773 return;
246242 }
247243
248244 uint8_t XCOFFObjectFile::getBytesInAddress() const {
249 uint8_t Result = 0;
250 llvm_unreachable("Not yet implemented!");
251 return Result;
245 // Only support 32-bit object files for now ...
246 assert(getFileHeaderSize() == XCOFF32FileHeaderSize);
247 return 4;
252248 }
253249
254250 StringRef XCOFFObjectFile::getFileFormatName() const {
297293 getNumberOfSections() * getSectionHeaderSize())))
298294 return;
299295 }
296 }
297
298 uint16_t XCOFFObjectFile::getMagic() const {
299 return FileHdrPtr->Magic;
300 }
301
302 uint16_t XCOFFObjectFile::getNumberOfSections() const {
303 return FileHdrPtr->NumberOfSections;
304 }
305
306 int32_t XCOFFObjectFile::getTimeStamp() const {
307 return FileHdrPtr->TimeStamp;
308 }
309
310 uint32_t XCOFFObjectFile::getSymbolTableOffset() const {
311 return FileHdrPtr->SymbolTableOffset;
312 }
313
314 int32_t XCOFFObjectFile::getNumberOfSymbolTableEntries() const {
315 // As far as symbol table size is concerned, if this field is negative it is
316 // to be treated as a 0. However since this field is also used for printing we
317 // don't want to truncate any negative values.
318 return FileHdrPtr->NumberOfSymTableEntries;
319 }
320
321 uint16_t XCOFFObjectFile::getOptionalHeaderSize() const {
322 return FileHdrPtr->AuxHeaderSize;
323 }
324
325 uint16_t XCOFFObjectFile::getFlags() const {
326 return FileHdrPtr->Flags;
300327 }
301328
302329 Expected>
0 # RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic.o | \
1 # RUN: FileCheck --check-prefix=FILEHEADER %s
2
3 # RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-time.o | \
4 # RUN: FileCheck --check-prefix=NEGTIME %s
5
6 # RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-sym-count.o | \
7 # RUN: FileCheck --check-prefix=NEGSYMCOUNT %s
8
9 # FILEHEADER: File: {{.*}}xcoff-basic.o
10 # FILEHEADER-NEXT: Format: aixcoff-rs6000
11 # FILEHEADER-NEXT: Arch: powerpc
12 # FILEHEADER-NEXT: AddressSize: 32bit
13 # FILEHEADER-NEXT: FileHeader {
14 # FILEHEADER-NEXT: Magic: 0x1DF
15 # FILEHEADER-NEXT: NumberOfSections: 6
16 # FILEHEADER-NEXT: TimeStamp: 2019-03-12T14:04:43Z (0x5C87BC7B)
17 # FILEHEADER-NEXT: SymbolTableOffset: 0x52E
18 # FILEHEADER-NEXT: SymbolTableEntries: 120
19 # FILEHEADER-NEXT: OptionalHeaderSize: 0x1C
20 # FILEHEADER-NEXT: Flags: 0x0
21 # FILEHEADER-NEXT: }
22
23 # NEGTIME: File: {{.*}}xcoff-basic-neg-time.o
24 # NEGTIME-NEXT: Format: aixcoff-rs6000
25 # NEGTIME-NEXT: Arch: powerpc
26 # NEGTIME-NEXT: AddressSize: 32bit
27 # NEGTIME-NEXT: FileHeader {
28 # NEGTIME-NEXT: Magic: 0x1DF
29 # NEGTIME-NEXT: NumberOfSections: 6
30 # NEGTIME-NEXT: TimeStamp: Reserved Value (0xDC87BC7B)
31 # NEGTIME-NEXT: SymbolTableOffset: 0x52E
32 # NEGTIME-NEXT: SymbolTableEntries: 120
33 # NEGTIME-NEXT: OptionalHeaderSize: 0x1C
34 # NEGTIME-NEXT: Flags: 0x0
35 # NEGTIME-NEXT: }
36
37 # NEGSYMCOUNT: File: {{.*}}xcoff-basic-neg-sym-count.o
38 # NEGSYMCOUNT-NEXT: Format: aixcoff-rs6000
39 # NEGSYMCOUNT-NEXT: Arch: powerpc
40 # NEGSYMCOUNT-NEXT: AddressSize: 32bit
41 # NEGSYMCOUNT-NEXT: FileHeader {
42 # NEGSYMCOUNT-NEXT: Magic: 0x1DF
43 # NEGSYMCOUNT-NEXT: NumberOfSections: 5
44 # NEGSYMCOUNT-NEXT: TimeStamp: 2019-03-12T14:04:43Z (0x5C87BC7B)
45 # NEGSYMCOUNT-NEXT: SymbolTableOffset: 0x0
46 # NEGSYMCOUNT-NEXT: SymbolTableEntries: Reserved Value (0x80000000)
47 # NEGSYMCOUNT-NEXT: OptionalHeaderSize: 0x1C
48 # NEGSYMCOUNT-NEXT: Flags: 0xD
49 # NEGSYMCOUNT-NEXT: }
50
51 # xcoff-basic.o was compiled with `xlc -qtls -O3 -g -c xcoff-basic.c`
52 # from the following source:
53 # int a = 55;
54 # int b;
55 # __thread int j = 55;
56 # __thread double d;
57 # int A() { return a; }
58 # int B() { return b; }
59 # int J() { return j; }
60 # double D() { return d; }
61 #
62 # xcoff-basic-neg-time.o was manually edited to include a negative time stamp.
63 # xcoff-basic-neg-sym-count.o was stripped using the 'strip' utility, and
64 # manually edited to have a negative symbol table entry count.
65
2121 WasmDumper.cpp
2222 Win64EHDumper.cpp
2323 WindowsResourceDumper.cpp
24 XCOFFDumper.cpp
2425 )
2526
2627 add_llvm_tool_symlink(llvm-readelf llvm-readobj)
132132 ScopedPrinter &Writer,
133133 std::unique_ptr &Result);
134134
135 std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
136 ScopedPrinter &Writer,
137 std::unique_ptr &Result);
138
135139 void dumpCOFFImportFile(const object::COFFImportFile *File,
136140 ScopedPrinter &Writer);
137141
0 //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file implements an XCOFF specific dumper for llvm-readobj.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "Error.h"
13 #include "ObjDumper.h"
14 #include "llvm-readobj.h"
15 #include "llvm/Object/XCOFFObjectFile.h"
16 #include "llvm/Support/ScopedPrinter.h"
17
18 using namespace llvm;
19 using namespace object;
20
21 namespace {
22
23 class XCOFFDumper : public ObjDumper {
24 public:
25 XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
26 : ObjDumper(Writer), Obj(Obj) {}
27
28 void printFileHeaders() override;
29 void printSectionHeaders() override;
30 void printRelocations() override;
31 void printSymbols() override;
32 void printDynamicSymbols() override;
33 void printUnwindInfo() override;
34 void printStackMap() const override;
35 void printNeededLibraries() override;
36
37 private:
38 const XCOFFObjectFile &Obj;
39 };
40 } // anonymous namespace
41
42 void XCOFFDumper::printFileHeaders() {
43 DictScope DS(W, "FileHeader");
44 W.printHex("Magic", Obj.getMagic());
45 W.printNumber("NumberOfSections", Obj.getNumberOfSections());
46
47 // Negative timestamp values are reserved for future use.
48 int32_t TimeStamp = Obj.getTimeStamp();
49 if (TimeStamp > 0) {
50 // This handling of the time stamp assumes that the host system's time_t is
51 // compatible with AIX time_t. If a platform is not compatible, the lit
52 // tests will let us know.
53 time_t TimeDate = TimeStamp;
54
55 char FormattedTime[21] = {};
56 size_t BytesWritten =
57 strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
58 if (BytesWritten)
59 W.printHex("TimeStamp", FormattedTime, TimeStamp);
60 else
61 W.printHex("Timestamp", TimeStamp);
62 } else {
63 W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
64 TimeStamp);
65 }
66
67 W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset());
68 int32_t SymTabEntries = Obj.getNumberOfSymbolTableEntries();
69 if (SymTabEntries >= 0)
70 W.printNumber("SymbolTableEntries", SymTabEntries);
71 else
72 W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
73
74 W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
75 W.printHex("Flags", Obj.getFlags());
76
77 // TODO FIXME Add support for the auxiliary header (if any) once
78 // XCOFFObjectFile has the necessary support.
79 }
80
81 void XCOFFDumper::printSectionHeaders() {
82 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
83 }
84
85 void XCOFFDumper::printRelocations() {
86 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
87 }
88
89 void XCOFFDumper::printSymbols() {
90 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
91 }
92
93 void XCOFFDumper::printDynamicSymbols() {
94 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
95 }
96
97 void XCOFFDumper::printUnwindInfo() {
98 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
99 }
100
101 void XCOFFDumper::printStackMap() const {
102 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
103 }
104
105 void XCOFFDumper::printNeededLibraries() {
106 llvm_unreachable("Unimplemented functionality for XCOFFDumper");
107 }
108
109 namespace llvm {
110 std::error_code createXCOFFDumper(const object::ObjectFile *Obj,
111 ScopedPrinter &Writer,
112 std::unique_ptr &Result) {
113 const XCOFFObjectFile *XObj = dyn_cast(Obj);
114 if (!XObj)
115 return readobj_error::unsupported_obj_file_format;
116
117 Result.reset(new XCOFFDumper(*XObj, Writer));
118 return readobj_error::success;
119 }
120 } // namespace llvm
439439 return createMachODumper(Obj, Writer, Result);
440440 if (Obj->isWasm())
441441 return createWasmDumper(Obj, Writer, Result);
442 if (Obj->isXCOFF())
443 return createXCOFFDumper(Obj, Writer, Result);
442444
443445 return readobj_error::unsupported_obj_file_format;
444446 }