Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
35231 views
1
//===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements an XCOFF specific dumper for llvm-readobj.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "ObjDumper.h"
14
#include "llvm-readobj.h"
15
#include "llvm/Demangle/Demangle.h"
16
#include "llvm/Object/XCOFFObjectFile.h"
17
#include "llvm/Support/FormattedStream.h"
18
#include "llvm/Support/ScopedPrinter.h"
19
20
#include <ctime>
21
22
using namespace llvm;
23
using namespace object;
24
25
namespace {
26
27
class XCOFFDumper : public ObjDumper {
28
29
public:
30
XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
31
: ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
32
33
void printFileHeaders() override;
34
void printAuxiliaryHeader() override;
35
void printSectionHeaders() override;
36
void printRelocations() override;
37
void printSymbols(bool ExtraSymInfo) override;
38
void printDynamicSymbols() override;
39
void printUnwindInfo() override;
40
void printStackMap() const override;
41
void printNeededLibraries() override;
42
void printStringTable() override;
43
void printExceptionSection() override;
44
void printLoaderSection(bool PrintHeader, bool PrintSymbols,
45
bool PrintRelocations) override;
46
47
ScopedPrinter &getScopedPrinter() const { return W; }
48
49
private:
50
template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
51
template <typename T> void printGenericSectionHeader(T &Sec) const;
52
template <typename T> void printOverflowSectionHeader(T &Sec) const;
53
template <typename T>
54
void printExceptionSectionEntry(const T &ExceptionSectEnt) const;
55
template <typename T> void printExceptionSectionEntries() const;
56
template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
57
void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
58
void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
59
void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
60
void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);
61
void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);
62
void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);
63
void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);
64
void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);
65
template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);
66
void printSymbol(const SymbolRef &);
67
template <typename RelTy> void printRelocation(RelTy Reloc);
68
template <typename Shdr, typename RelTy>
69
void printRelocations(ArrayRef<Shdr> Sections);
70
void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
71
void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
72
void printLoaderSectionHeader(uintptr_t LoaderSectAddr);
73
void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);
74
template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
75
void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);
76
template <typename LoadSectionRelocTy>
77
void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,
78
StringRef SymbolName);
79
void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);
80
template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
81
typename LoaderSectionRelocationEntry>
82
void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);
83
84
const XCOFFObjectFile &Obj;
85
const static int32_t FirstSymIdxOfLoaderSec = 3;
86
};
87
} // anonymous namespace
88
89
void XCOFFDumper::printFileHeaders() {
90
DictScope DS(W, "FileHeader");
91
W.printHex("Magic", Obj.getMagic());
92
W.printNumber("NumberOfSections", Obj.getNumberOfSections());
93
94
// Negative timestamp values are reserved for future use.
95
int32_t TimeStamp = Obj.getTimeStamp();
96
if (TimeStamp > 0) {
97
// This handling of the time stamp assumes that the host system's time_t is
98
// compatible with AIX time_t. If a platform is not compatible, the lit
99
// tests will let us know.
100
time_t TimeDate = TimeStamp;
101
102
char FormattedTime[80] = {};
103
104
size_t BytesFormatted =
105
strftime(FormattedTime, sizeof(FormattedTime), "%F %T", gmtime(&TimeDate));
106
if (BytesFormatted)
107
W.printHex("TimeStamp", FormattedTime, TimeStamp);
108
else
109
W.printHex("Timestamp", TimeStamp);
110
} else {
111
W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
112
TimeStamp);
113
}
114
115
// The number of symbol table entries is an unsigned value in 64-bit objects
116
// and a signed value (with negative values being 'reserved') in 32-bit
117
// objects.
118
if (Obj.is64Bit()) {
119
W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
120
W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
121
} else {
122
W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
123
int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
124
if (SymTabEntries >= 0)
125
W.printNumber("SymbolTableEntries", SymTabEntries);
126
else
127
W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
128
}
129
130
W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
131
W.printHex("Flags", Obj.getFlags());
132
133
// TODO FIXME Add support for the auxiliary header (if any) once
134
// XCOFFObjectFile has the necessary support.
135
}
136
137
void XCOFFDumper::printAuxiliaryHeader() {
138
DictScope DS(W, "AuxiliaryHeader");
139
140
if (Obj.is64Bit())
141
printAuxiliaryHeader(Obj.auxiliaryHeader64());
142
else
143
printAuxiliaryHeader(Obj.auxiliaryHeader32());
144
}
145
146
void XCOFFDumper::printSectionHeaders() {
147
if (Obj.is64Bit())
148
printSectionHeaders(Obj.sections64());
149
else
150
printSectionHeaders(Obj.sections32());
151
}
152
153
void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,
154
bool PrintRelocations) {
155
DictScope DS(W, "Loader Section");
156
Expected<uintptr_t> LoaderSectionAddrOrError =
157
Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
158
if (!LoaderSectionAddrOrError) {
159
reportUniqueWarning(LoaderSectionAddrOrError.takeError());
160
return;
161
}
162
uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
163
164
if (LoaderSectionAddr == 0)
165
return;
166
167
W.indent();
168
if (PrintHeader)
169
printLoaderSectionHeader(LoaderSectionAddr);
170
171
if (PrintSymbols)
172
printLoaderSectionSymbols(LoaderSectionAddr);
173
174
if (PrintRelocations)
175
printLoaderSectionRelocationEntries(LoaderSectionAddr);
176
177
W.unindent();
178
}
179
180
void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {
181
DictScope DS(W, "Loader Section Header");
182
183
auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {
184
W.printNumber("Version", LDHeader->Version);
185
W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);
186
W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);
187
W.printNumber("LengthOfImportFileIDStringTable",
188
LDHeader->LengthOfImpidStrTbl);
189
W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);
190
W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);
191
W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);
192
W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);
193
};
194
195
if (Obj.is64Bit()) {
196
const LoaderSectionHeader64 *LoaderSec64 =
197
reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);
198
PrintLoadSecHeaderCommon(LoaderSec64);
199
W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);
200
W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);
201
} else {
202
const LoaderSectionHeader32 *LoaderSec32 =
203
reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);
204
PrintLoadSecHeaderCommon(LoaderSec32);
205
}
206
}
207
208
const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
209
#define ECase(X) \
210
{ #X, XCOFF::X }
211
ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
212
ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
213
ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
214
ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
215
ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
216
ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
217
ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
218
ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
219
ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
220
ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
221
ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
222
ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
223
ECase(C_STTLS), ECase(C_EFCN)
224
#undef ECase
225
};
226
227
template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
228
void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {
229
const LoaderSectionHeader *LoadSecHeader =
230
reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
231
const LoaderSectionSymbolEntry *LoadSecSymEntPtr =
232
reinterpret_cast<LoaderSectionSymbolEntry *>(
233
LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));
234
235
for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;
236
++i, ++LoadSecSymEntPtr) {
237
if (Error E = Binary::checkOffset(
238
Obj.getMemoryBufferRef(),
239
LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +
240
(i * sizeof(LoaderSectionSymbolEntry)),
241
sizeof(LoaderSectionSymbolEntry))) {
242
reportUniqueWarning(std::move(E));
243
return;
244
}
245
246
Expected<StringRef> SymbolNameOrErr =
247
LoadSecSymEntPtr->getSymbolName(LoadSecHeader);
248
if (!SymbolNameOrErr) {
249
reportUniqueWarning(SymbolNameOrErr.takeError());
250
return;
251
}
252
253
DictScope DS(W, "Symbol");
254
StringRef SymbolName = SymbolNameOrErr.get();
255
W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);
256
W.printHex("Virtual Address", LoadSecSymEntPtr->Value);
257
W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);
258
W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);
259
W.printEnum("StorageClass",
260
static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),
261
ArrayRef(SymStorageClass));
262
W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);
263
W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);
264
}
265
}
266
267
void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {
268
DictScope DS(W, "Loader Section Symbols");
269
if (Obj.is64Bit())
270
printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,
271
LoaderSectionHeader64>(LoaderSectionAddr);
272
else
273
printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,
274
LoaderSectionHeader32>(LoaderSectionAddr);
275
}
276
277
const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
278
#define ECase(X) \
279
{ #X, XCOFF::X }
280
ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
281
ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
282
ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
283
ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
284
ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
285
ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
286
#undef ECase
287
};
288
289
// From the XCOFF specification: there are five implicit external symbols, one
290
// each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
291
// are referenced from the relocation table entries using symbol table index
292
// values 0, 1, 2, -1, and -2, respectively.
293
static const char *getImplicitLoaderSectionSymName(int SymIndx) {
294
switch (SymIndx) {
295
default:
296
return "Unkown Symbol Name";
297
case -2:
298
return ".tbss";
299
case -1:
300
return ".tdata";
301
case 0:
302
return ".text";
303
case 1:
304
return ".data";
305
case 2:
306
return ".bss";
307
}
308
}
309
310
template <typename LoadSectionRelocTy>
311
void XCOFFDumper::printLoaderSectionRelocationEntry(
312
LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {
313
uint16_t Type = LoaderSecRelEntPtr->Type;
314
if (opts::ExpandRelocs) {
315
DictScope DS(W, "Relocation");
316
auto IsRelocationSigned = [](uint8_t Info) {
317
return Info & XCOFF::XR_SIGN_INDICATOR_MASK;
318
};
319
auto IsFixupIndicated = [](uint8_t Info) {
320
return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;
321
};
322
auto GetRelocatedLength = [](uint8_t Info) {
323
// The relocation encodes the bit length being relocated minus 1. Add
324
// back
325
// the 1 to get the actual length being relocated.
326
return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;
327
};
328
329
uint8_t Info = Type >> 8;
330
W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);
331
W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,
332
LoaderSecRelEntPtr->SymbolIndex);
333
W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");
334
W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);
335
W.printNumber("Length", GetRelocatedLength(Info));
336
W.printEnum("Type", static_cast<uint8_t>(Type),
337
ArrayRef(RelocationTypeNameclass));
338
W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);
339
} else {
340
W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,
341
Obj.is64Bit() ? 18 : 10)
342
<< " " << format_hex(Type, 6) << " ("
343
<< XCOFF::getRelocationTypeString(
344
static_cast<XCOFF::RelocationType>(Type))
345
<< ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)
346
<< " "
347
<< (opts::Demangle ? demangle(SymbolName) : SymbolName)
348
<< " (" << LoaderSecRelEntPtr->SymbolIndex << ")\n";
349
}
350
}
351
352
template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
353
typename LoaderSectionRelocationEntry>
354
void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
355
uintptr_t LoaderSectionAddr) {
356
const LoaderSectionHeader *LoaderSec =
357
reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
358
const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =
359
reinterpret_cast<const LoaderSectionRelocationEntry *>(
360
LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));
361
362
if (!opts::ExpandRelocs)
363
W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)
364
<< center_justify("Type", 15) << right_justify("SecNum", 8)
365
<< center_justify("SymbolName (Index) ", 24) << "\n";
366
367
for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;
368
++i, ++LoaderSecRelEntPtr) {
369
StringRef SymbolName;
370
if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {
371
// Because there are implicit symbol index values (-2, -1, 0, 1, 2),
372
// LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
373
// real symbol from the symbol table.
374
const uint64_t SymOffset =
375
(LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *
376
sizeof(LoaderSectionSymbolEntry);
377
const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =
378
reinterpret_cast<LoaderSectionSymbolEntry *>(
379
LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +
380
SymOffset);
381
382
Expected<StringRef> SymbolNameOrErr =
383
LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);
384
if (!SymbolNameOrErr) {
385
reportUniqueWarning(SymbolNameOrErr.takeError());
386
return;
387
}
388
SymbolName = SymbolNameOrErr.get();
389
} else
390
SymbolName =
391
getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);
392
393
printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);
394
}
395
}
396
397
void XCOFFDumper::printLoaderSectionRelocationEntries(
398
uintptr_t LoaderSectionAddr) {
399
DictScope DS(W, "Loader Section Relocations");
400
401
if (Obj.is64Bit())
402
printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,
403
LoaderSectionSymbolEntry64,
404
LoaderSectionRelocationEntry64>(
405
LoaderSectionAddr);
406
else
407
printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,
408
LoaderSectionSymbolEntry32,
409
LoaderSectionRelocationEntry32>(
410
LoaderSectionAddr);
411
}
412
413
template <typename T>
414
void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
415
if (ExceptionSectEnt.getReason())
416
W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());
417
else {
418
uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();
419
Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);
420
if (Error E = ErrOrSymbolName.takeError()) {
421
reportUniqueWarning(std::move(E));
422
return;
423
}
424
StringRef SymName = *ErrOrSymbolName;
425
426
W.printNumber("Symbol", SymName, SymIdx);
427
}
428
W.printNumber("LangID", ExceptionSectEnt.getLangID());
429
W.printNumber("Reason", ExceptionSectEnt.getReason());
430
}
431
432
template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {
433
Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();
434
if (Error E = ExceptSectEntsOrErr.takeError()) {
435
reportUniqueWarning(std::move(E));
436
return;
437
}
438
ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;
439
440
DictScope DS(W, "Exception section");
441
if (ExceptSectEnts.empty())
442
return;
443
for (auto &Ent : ExceptSectEnts)
444
printExceptionSectionEntry(Ent);
445
}
446
447
void XCOFFDumper::printExceptionSection() {
448
if (Obj.is64Bit())
449
printExceptionSectionEntries<ExceptionSectionEntry64>();
450
else
451
printExceptionSectionEntries<ExceptionSectionEntry32>();
452
}
453
454
void XCOFFDumper::printRelocations() {
455
if (Obj.is64Bit())
456
printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
457
else
458
printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
459
}
460
461
template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
462
Expected<StringRef> ErrOrSymbolName =
463
Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
464
if (Error E = ErrOrSymbolName.takeError()) {
465
reportUniqueWarning(std::move(E));
466
return;
467
}
468
StringRef SymbolName = *ErrOrSymbolName;
469
StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);
470
if (opts::ExpandRelocs) {
471
DictScope Group(W, "Relocation");
472
W.printHex("Virtual Address", Reloc.VirtualAddress);
473
W.printNumber("Symbol", opts::Demangle ? demangle(SymbolName) : SymbolName,
474
Reloc.SymbolIndex);
475
W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
476
W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
477
W.printNumber("Length", Reloc.getRelocatedLength());
478
W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));
479
} else {
480
raw_ostream &OS = W.startLine();
481
OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " "
482
<< (opts::Demangle ? demangle(SymbolName) : SymbolName) << "("
483
<< Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";
484
}
485
}
486
487
template <typename Shdr, typename RelTy>
488
void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {
489
ListScope LS(W, "Relocations");
490
uint16_t Index = 0;
491
for (const Shdr &Sec : Sections) {
492
++Index;
493
// Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
494
if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
495
Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
496
continue;
497
Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);
498
if (Error E = ErrOrRelocations.takeError()) {
499
reportUniqueWarning(std::move(E));
500
continue;
501
}
502
503
const ArrayRef<RelTy> Relocations = *ErrOrRelocations;
504
if (Relocations.empty())
505
continue;
506
507
W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
508
<< " {\n";
509
W.indent();
510
511
for (const RelTy Reloc : Relocations)
512
printRelocation(Reloc);
513
514
W.unindent();
515
W.startLine() << "}\n";
516
}
517
}
518
519
const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
520
#define ECase(X) \
521
{ #X, XCOFF::X }
522
ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
523
#undef ECase
524
};
525
526
const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
527
#define ECase(X) \
528
{ #X, XCOFF::X }
529
ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
530
ECase(AUX_CSECT), ECase(AUX_SECT)
531
#undef ECase
532
};
533
534
void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
535
assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
536
"Mismatched auxiliary type!");
537
StringRef FileName =
538
unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
539
DictScope SymDs(W, "File Auxiliary Entry");
540
W.printNumber("Index",
541
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
542
W.printString("Name", FileName);
543
W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
544
ArrayRef(FileStringType));
545
if (Obj.is64Bit()) {
546
W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
547
ArrayRef(SymAuxType));
548
}
549
}
550
551
static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
552
{
553
#define ECase(X) \
554
{ #X, XCOFF::X }
555
ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), ECase(XMC_GL),
556
ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
557
ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
558
ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), ECase(XMC_UA),
559
ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL), ECase(XMC_UL),
560
ECase(XMC_TE)
561
#undef ECase
562
};
563
564
const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
565
#define ECase(X) \
566
{ #X, XCOFF::X }
567
ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
568
#undef ECase
569
};
570
571
void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
572
assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
573
"Mismatched auxiliary type!");
574
575
DictScope SymDs(W, "CSECT Auxiliary Entry");
576
W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
577
W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
578
: "SectionLen",
579
AuxEntRef.getSectionOrLength());
580
W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
581
W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
582
// Print out symbol alignment and type.
583
W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
584
W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
585
ArrayRef(CsectSymbolTypeClass));
586
W.printEnum("StorageMappingClass",
587
static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
588
ArrayRef(CsectStorageMappingClass));
589
590
if (Obj.is64Bit()) {
591
W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
592
ArrayRef(SymAuxType));
593
} else {
594
W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
595
W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
596
}
597
}
598
599
void XCOFFDumper::printSectAuxEntForStat(
600
const XCOFFSectAuxEntForStat *AuxEntPtr) {
601
assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
602
603
DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
604
W.printNumber("Index",
605
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
606
W.printNumber("SectionLength", AuxEntPtr->SectionLength);
607
608
// Unlike the corresponding fields in the section header, NumberOfRelocEnt
609
// and NumberOfLineNum do not handle values greater than 65535.
610
W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
611
W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
612
}
613
614
void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {
615
assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
616
617
DictScope SymDs(W, "Exception Auxiliary Entry");
618
W.printNumber("Index",
619
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
620
W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
621
W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
622
W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
623
W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
624
ArrayRef(SymAuxType));
625
}
626
627
void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {
628
assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
629
630
DictScope SymDs(W, "Function Auxiliary Entry");
631
W.printNumber("Index",
632
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
633
W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
634
W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
635
W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
636
W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
637
}
638
639
void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {
640
assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
641
642
DictScope SymDs(W, "Function Auxiliary Entry");
643
W.printNumber("Index",
644
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
645
W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
646
W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
647
W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
648
W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
649
ArrayRef(SymAuxType));
650
}
651
652
void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {
653
assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
654
655
DictScope SymDs(W, "Block Auxiliary Entry");
656
W.printNumber("Index",
657
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
658
W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);
659
W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);
660
}
661
662
void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {
663
assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
664
665
DictScope SymDs(W, "Block Auxiliary Entry");
666
W.printNumber("Index",
667
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
668
W.printHex("LineNumber", AuxEntPtr->LineNum);
669
W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
670
ArrayRef(SymAuxType));
671
}
672
673
template <typename T>
674
void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {
675
DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");
676
W.printNumber("Index",
677
Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
678
W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);
679
W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);
680
if (Obj.is64Bit())
681
W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),
682
ArrayRef(SymAuxType));
683
}
684
685
static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
686
switch (SC) {
687
case XCOFF::C_EXT:
688
case XCOFF::C_WEAKEXT:
689
case XCOFF::C_HIDEXT:
690
case XCOFF::C_STAT:
691
case XCOFF::C_FCN:
692
case XCOFF::C_BLOCK:
693
return "Value (RelocatableAddress)";
694
case XCOFF::C_FILE:
695
return "Value (SymbolTableIndex)";
696
case XCOFF::C_DWARF:
697
return "Value (OffsetInDWARF)";
698
case XCOFF::C_FUN:
699
case XCOFF::C_STSYM:
700
case XCOFF::C_BINCL:
701
case XCOFF::C_EINCL:
702
case XCOFF::C_INFO:
703
case XCOFF::C_BSTAT:
704
case XCOFF::C_LSYM:
705
case XCOFF::C_PSYM:
706
case XCOFF::C_RPSYM:
707
case XCOFF::C_RSYM:
708
case XCOFF::C_ECOML:
709
assert(false && "This StorageClass for the symbol is not yet implemented.");
710
return "";
711
default:
712
return "Value";
713
}
714
}
715
716
const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
717
#define ECase(X) \
718
{ #X, XCOFF::X }
719
ECase(TB_C), ECase(TB_Fortran), ECase(TB_CPLUSPLUS)
720
#undef ECase
721
};
722
723
const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
724
#define ECase(X) \
725
{ #X, XCOFF::X }
726
ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
727
#undef ECase
728
};
729
730
template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {
731
const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);
732
Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));
733
return AuxEntPtr;
734
}
735
736
static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {
737
W.startLine() << "!Unexpected raw auxiliary entry data:\n";
738
W.startLine() << format_bytes(
739
ArrayRef<uint8_t>(
740
reinterpret_cast<const uint8_t *>(AuxAddress),
741
XCOFF::SymbolTableEntrySize),
742
std::nullopt, XCOFF::SymbolTableEntrySize)
743
<< "\n";
744
}
745
746
void XCOFFDumper::printSymbol(const SymbolRef &S) {
747
DataRefImpl SymbolDRI = S.getRawDataRefImpl();
748
XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
749
750
uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
751
752
DictScope SymDs(W, "Symbol");
753
754
StringRef SymbolName =
755
unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
756
757
uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
758
XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();
759
760
W.printNumber("Index", SymbolIdx);
761
W.printString("Name", opts::Demangle ? demangle(SymbolName) : SymbolName);
762
W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());
763
764
StringRef SectionName =
765
unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
766
767
W.printString("Section", SectionName);
768
if (SymbolClass == XCOFF::C_FILE) {
769
W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
770
ArrayRef(CFileLangIdClass));
771
W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
772
ArrayRef(CFileCpuIdClass));
773
} else
774
W.printHex("Type", SymbolEntRef.getSymbolType());
775
776
W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),
777
ArrayRef(SymStorageClass));
778
W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
779
780
if (NumberOfAuxEntries == 0)
781
return;
782
783
auto checkNumOfAux = [=] {
784
if (NumberOfAuxEntries > 1)
785
reportUniqueWarning("the " +
786
enumToString(static_cast<uint8_t>(SymbolClass),
787
ArrayRef(SymStorageClass)) +
788
" symbol at index " + Twine(SymbolIdx) +
789
" should not have more than 1 "
790
"auxiliary entry");
791
};
792
793
switch (SymbolClass) {
794
case XCOFF::C_FILE:
795
// If the symbol is C_FILE and has auxiliary entries...
796
for (int I = 1; I <= NumberOfAuxEntries; I++) {
797
uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
798
SymbolEntRef.getEntryAddress(), I);
799
800
if (Obj.is64Bit() &&
801
*Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
802
printUnexpectedRawAuxEnt(W, AuxAddress);
803
continue;
804
}
805
806
const XCOFFFileAuxEnt *FileAuxEntPtr =
807
getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
808
printFileAuxEnt(FileAuxEntPtr);
809
}
810
break;
811
case XCOFF::C_EXT:
812
case XCOFF::C_WEAKEXT:
813
case XCOFF::C_HIDEXT: {
814
// For 32-bit objects, print the function auxiliary symbol table entry. The
815
// last one must be a CSECT auxiliary entry.
816
// For 64-bit objects, both a function auxiliary entry and an exception
817
// auxiliary entry may appear, print them in the loop and skip printing the
818
// CSECT auxiliary entry, which will be printed outside the loop.
819
for (int I = 1; I <= NumberOfAuxEntries; I++) {
820
if (I == NumberOfAuxEntries && !Obj.is64Bit())
821
break;
822
823
uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
824
SymbolEntRef.getEntryAddress(), I);
825
826
if (Obj.is64Bit()) {
827
XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
828
if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
829
continue;
830
if (Type == XCOFF::SymbolAuxType::AUX_FCN) {
831
const XCOFFFunctionAuxEnt64 *AuxEntPtr =
832
getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
833
printFunctionAuxEnt(AuxEntPtr);
834
} else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {
835
const XCOFFExceptionAuxEnt *AuxEntPtr =
836
getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
837
printExceptionAuxEnt(AuxEntPtr);
838
} else {
839
printUnexpectedRawAuxEnt(W, AuxAddress);
840
}
841
} else {
842
const XCOFFFunctionAuxEnt32 *AuxEntPtr =
843
getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
844
printFunctionAuxEnt(AuxEntPtr);
845
}
846
}
847
848
// Print the CSECT auxiliary entry.
849
auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
850
if (!ErrOrCsectAuxRef)
851
reportUniqueWarning(ErrOrCsectAuxRef.takeError());
852
else
853
printCsectAuxEnt(*ErrOrCsectAuxRef);
854
855
break;
856
}
857
case XCOFF::C_STAT: {
858
checkNumOfAux();
859
860
const XCOFFSectAuxEntForStat *StatAuxEntPtr =
861
getAuxEntPtr<XCOFFSectAuxEntForStat>(
862
XCOFFObjectFile::getAdvancedSymbolEntryAddress(
863
SymbolEntRef.getEntryAddress(), 1));
864
printSectAuxEntForStat(StatAuxEntPtr);
865
break;
866
}
867
case XCOFF::C_DWARF: {
868
checkNumOfAux();
869
870
uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
871
SymbolEntRef.getEntryAddress(), 1);
872
873
if (Obj.is64Bit()) {
874
const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
875
getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
876
printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);
877
} else {
878
const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
879
getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
880
printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);
881
}
882
break;
883
}
884
case XCOFF::C_BLOCK:
885
case XCOFF::C_FCN: {
886
checkNumOfAux();
887
888
uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
889
SymbolEntRef.getEntryAddress(), 1);
890
891
if (Obj.is64Bit()) {
892
const XCOFFBlockAuxEnt64 *AuxEntPtr =
893
getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
894
printBlockAuxEnt(AuxEntPtr);
895
} else {
896
const XCOFFBlockAuxEnt32 *AuxEntPtr =
897
getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
898
printBlockAuxEnt(AuxEntPtr);
899
}
900
break;
901
}
902
default:
903
for (int i = 1; i <= NumberOfAuxEntries; i++) {
904
printUnexpectedRawAuxEnt(W,
905
XCOFFObjectFile::getAdvancedSymbolEntryAddress(
906
SymbolEntRef.getEntryAddress(), i));
907
}
908
break;
909
}
910
}
911
912
void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
913
ListScope Group(W, "Symbols");
914
for (const SymbolRef &S : Obj.symbols())
915
printSymbol(S);
916
}
917
918
void XCOFFDumper::printStringTable() {
919
DictScope DS(W, "StringTable");
920
StringRef StrTable = Obj.getStringTable();
921
uint32_t StrTabSize = StrTable.size();
922
W.printNumber("Length", StrTabSize);
923
// Print strings from the fifth byte, since the first four bytes contain the
924
// length (in bytes) of the string table (including the length field).
925
if (StrTabSize > 4)
926
printAsStringList(StrTable, 4);
927
}
928
929
void XCOFFDumper::printDynamicSymbols() {
930
llvm_unreachable("Unimplemented functionality for XCOFFDumper");
931
}
932
933
void XCOFFDumper::printUnwindInfo() {
934
llvm_unreachable("Unimplemented functionality for XCOFFDumper");
935
}
936
937
void XCOFFDumper::printStackMap() const {
938
llvm_unreachable("Unimplemented functionality for XCOFFDumper");
939
}
940
941
void XCOFFDumper::printNeededLibraries() {
942
ListScope D(W, "NeededLibraries");
943
auto ImportFilesOrError = Obj.getImportFileTable();
944
if (!ImportFilesOrError) {
945
reportUniqueWarning(ImportFilesOrError.takeError());
946
return;
947
}
948
949
StringRef ImportFileTable = ImportFilesOrError.get();
950
const char *CurrentStr = ImportFileTable.data();
951
const char *TableEnd = ImportFileTable.end();
952
// Default column width for names is 13 even if no names are that long.
953
size_t BaseWidth = 13;
954
955
// Get the max width of BASE columns.
956
for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {
957
size_t CurrentLen = strlen(CurrentStr);
958
CurrentStr += strlen(CurrentStr) + 1;
959
if (StrIndex % 3 == 1)
960
BaseWidth = std::max(BaseWidth, CurrentLen);
961
}
962
963
auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());
964
// Each entry consists of 3 strings: the path_name, base_name and
965
// archive_member_name. The first entry is a default LIBPATH value and other
966
// entries have no path_name. We just dump the base_name and
967
// archive_member_name here.
968
OS << left_justify("BASE", BaseWidth) << " MEMBER\n";
969
CurrentStr = ImportFileTable.data();
970
for (size_t StrIndex = 0; CurrentStr < TableEnd;
971
++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {
972
if (StrIndex >= 3 && StrIndex % 3 != 0) {
973
if (StrIndex % 3 == 1)
974
OS << " " << left_justify(CurrentStr, BaseWidth) << " ";
975
else
976
OS << CurrentStr << "\n";
977
}
978
}
979
}
980
981
const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
982
#define ECase(X) \
983
{ #X, XCOFF::X }
984
ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),
985
ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),
986
ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),
987
ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
988
ECase(STYP_OVRFLO)
989
#undef ECase
990
};
991
992
const EnumEntry<XCOFF::DwarfSectionSubtypeFlags>
993
DWARFSectionSubtypeFlagsNames[] = {
994
#define ECase(X) \
995
{ #X, XCOFF::X }
996
ECase(SSUBTYP_DWINFO), ECase(SSUBTYP_DWLINE), ECase(SSUBTYP_DWPBNMS),
997
ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV),
998
ECase(SSUBTYP_DWSTR), ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC),
999
ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC)
1000
#undef ECase
1001
};
1002
1003
template <typename T>
1004
void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
1005
if (Obj.is64Bit()) {
1006
reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
1007
"contain an overflow section header.",
1008
object_error::parse_failed),
1009
Obj.getFileName());
1010
}
1011
1012
W.printString("Name", Sec.getName());
1013
W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
1014
W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
1015
W.printHex("Size", Sec.SectionSize);
1016
W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
1017
W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
1018
W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
1019
W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
1020
W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
1021
}
1022
1023
template <typename T>
1024
void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
1025
W.printString("Name", Sec.getName());
1026
W.printHex("PhysicalAddress", Sec.PhysicalAddress);
1027
W.printHex("VirtualAddress", Sec.VirtualAddress);
1028
W.printHex("Size", Sec.SectionSize);
1029
W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
1030
W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
1031
W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
1032
W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
1033
W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
1034
}
1035
1036
enum PrintStyle { Hex, Number };
1037
template <typename T, typename V>
1038
static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,
1039
const T &Member, const V *AuxHeader,
1040
uint16_t AuxSize, uint16_t &PartialFieldOffset,
1041
const char *&PartialFieldName,
1042
ScopedPrinter &W) {
1043
ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -
1044
reinterpret_cast<const char *>(AuxHeader);
1045
if (Offset + sizeof(Member) <= AuxSize)
1046
Style == Hex ? W.printHex(MemberName, Member)
1047
: W.printNumber(MemberName, Member);
1048
else if (Offset < AuxSize) {
1049
PartialFieldOffset = Offset;
1050
PartialFieldName = MemberName;
1051
}
1052
}
1053
1054
template <class T>
1055
void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,
1056
uint16_t PartialFieldOffset,
1057
uint16_t AuxSize, T &AuxHeader,
1058
XCOFFDumper *Dumper) {
1059
if (PartialFieldOffset < AuxSize) {
1060
Dumper->reportUniqueWarning(Twine("only partial field for ") +
1061
PartialFieldName + " at offset (" +
1062
Twine(PartialFieldOffset) + ")");
1063
Dumper->getScopedPrinter().printBinary(
1064
"Raw data", "",
1065
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
1066
PartialFieldOffset,
1067
AuxSize - PartialFieldOffset));
1068
} else if (sizeof(AuxHeader) < AuxSize)
1069
Dumper->getScopedPrinter().printBinary(
1070
"Extra raw data", "",
1071
ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
1072
sizeof(AuxHeader),
1073
AuxSize - sizeof(AuxHeader)));
1074
}
1075
1076
void XCOFFDumper::printAuxiliaryHeader(
1077
const XCOFFAuxiliaryHeader32 *AuxHeader) {
1078
if (AuxHeader == nullptr)
1079
return;
1080
uint16_t AuxSize = Obj.getOptionalHeaderSize();
1081
uint16_t PartialFieldOffset = AuxSize;
1082
const char *PartialFieldName = nullptr;
1083
1084
auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
1085
auto &Member) {
1086
printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
1087
PartialFieldOffset, PartialFieldName, W);
1088
};
1089
1090
PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
1091
PrintAuxMember(Hex, "Version", AuxHeader->Version);
1092
PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
1093
PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
1094
PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
1095
PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
1096
PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
1097
PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
1098
PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
1099
PrintAuxMember(Number, "Section number of entryPoint",
1100
AuxHeader->SecNumOfEntryPoint);
1101
PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
1102
PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
1103
PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
1104
PrintAuxMember(Number, "Section number of loader data",
1105
AuxHeader->SecNumOfLoader);
1106
PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
1107
PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
1108
PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
1109
PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
1110
PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
1111
PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
1112
PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
1113
PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
1114
PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
1115
PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
1116
PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
1117
PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
1118
if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +
1119
sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=
1120
AuxSize) {
1121
W.printHex("Flag", AuxHeader->getFlag());
1122
W.printHex("Alignment of thread-local storage",
1123
AuxHeader->getTDataAlignment());
1124
}
1125
1126
PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
1127
PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
1128
1129
checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
1130
AuxSize, *AuxHeader, this);
1131
}
1132
1133
void XCOFFDumper::printAuxiliaryHeader(
1134
const XCOFFAuxiliaryHeader64 *AuxHeader) {
1135
if (AuxHeader == nullptr)
1136
return;
1137
uint16_t AuxSize = Obj.getOptionalHeaderSize();
1138
uint16_t PartialFieldOffset = AuxSize;
1139
const char *PartialFieldName = nullptr;
1140
1141
auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
1142
auto &Member) {
1143
printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
1144
PartialFieldOffset, PartialFieldName, W);
1145
};
1146
1147
PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
1148
PrintAuxMember(Hex, "Version", AuxHeader->Version);
1149
PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
1150
PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
1151
PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
1152
PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
1153
PrintAuxMember(Number, "Section number of entryPoint",
1154
AuxHeader->SecNumOfEntryPoint);
1155
PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
1156
PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
1157
PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
1158
PrintAuxMember(Number, "Section number of loader data",
1159
AuxHeader->SecNumOfLoader);
1160
PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
1161
PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
1162
PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
1163
PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
1164
PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
1165
PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
1166
PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
1167
PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
1168
PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
1169
if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +
1170
sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=
1171
AuxSize) {
1172
W.printHex("Flag", AuxHeader->getFlag());
1173
W.printHex("Alignment of thread-local storage",
1174
AuxHeader->getTDataAlignment());
1175
}
1176
PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
1177
PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
1178
PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
1179
PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
1180
PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
1181
PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
1182
PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
1183
PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
1184
PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag);
1185
1186
checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
1187
AuxSize, *AuxHeader, this);
1188
}
1189
1190
template <typename T>
1191
void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
1192
ListScope Group(W, "Sections");
1193
1194
uint16_t Index = 1;
1195
for (const T &Sec : Sections) {
1196
DictScope SecDS(W, "Section");
1197
1198
W.printNumber("Index", Index++);
1199
uint16_t SectionType = Sec.getSectionType();
1200
int32_t SectionSubtype = Sec.getSectionSubtype();
1201
switch (SectionType) {
1202
case XCOFF::STYP_OVRFLO:
1203
printOverflowSectionHeader(Sec);
1204
break;
1205
case XCOFF::STYP_LOADER:
1206
case XCOFF::STYP_EXCEPT:
1207
case XCOFF::STYP_TYPCHK:
1208
// TODO The interpretation of loader, exception and type check section
1209
// headers are different from that of generic section headers. We will
1210
// implement them later. We interpret them as generic section headers for
1211
// now.
1212
default:
1213
printGenericSectionHeader(Sec);
1214
break;
1215
}
1216
if (Sec.isReservedSectionType())
1217
W.printHex("Flags", "Reserved", SectionType);
1218
else {
1219
W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));
1220
if (SectionType == XCOFF::STYP_DWARF) {
1221
W.printEnum("DWARFSubType", SectionSubtype,
1222
ArrayRef(DWARFSectionSubtypeFlagsNames));
1223
}
1224
}
1225
}
1226
1227
if (opts::SectionRelocations)
1228
report_fatal_error("Dumping section relocations is unimplemented");
1229
1230
if (opts::SectionSymbols)
1231
report_fatal_error("Dumping symbols is unimplemented");
1232
1233
if (opts::SectionData)
1234
report_fatal_error("Dumping section data is unimplemented");
1235
}
1236
1237
namespace llvm {
1238
std::unique_ptr<ObjDumper>
1239
createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
1240
return std::make_unique<XCOFFDumper>(XObj, Writer);
1241
}
1242
} // namespace llvm
1243
1244