[llvm] a274d62 - [XCOFF] Decode the relocation entries of loader section of xcoff for llvm-readobj
via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 14 08:16:40 PST 2022
Author: zhijian
Date: 2022-12-14T11:16:20-05:00
New Revision: a274d62fecfc3f49065f3fcdcb9577637778e0bc
URL: https://github.com/llvm/llvm-project/commit/a274d62fecfc3f49065f3fcdcb9577637778e0bc
DIFF: https://github.com/llvm/llvm-project/commit/a274d62fecfc3f49065f3fcdcb9577637778e0bc.diff
LOG: [XCOFF] Decode the relocation entries of loader section of xcoff for llvm-readobj
Summary:
support decoding the relocation entries of loader section of xcoff for llvm-readobj
https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format#XCOFF__vra3i31ejbau
Reviewers: James Henderson, Esme Yi
Differential Revision: https://reviews.llvm.org/D136787
Added:
llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation-invalid-sym-name.test
llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation.test
Modified:
llvm/docs/CommandGuide/llvm-readobj.rst
llvm/include/llvm/BinaryFormat/XCOFF.h
llvm/include/llvm/Object/XCOFFObjectFile.h
llvm/tools/llvm-readobj/ObjDumper.h
llvm/tools/llvm-readobj/Opts.td
llvm/tools/llvm-readobj/XCOFFDumper.cpp
llvm/tools/llvm-readobj/llvm-readobj.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index 64373755fdf31..6167190f0fa05 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -342,6 +342,10 @@ The following options are implemented only for the XCOFF file format.
Display symbol table of loader section.
+.. option:: --loader-section-relocations
+
+ Display relocation entries of loader section.
+
EXIT STATUS
-----------
diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h
index df5ad798dffd6..5774e01429d37 100644
--- a/llvm/include/llvm/BinaryFormat/XCOFF.h
+++ b/llvm/include/llvm/BinaryFormat/XCOFF.h
@@ -46,6 +46,18 @@ enum ReservedSectionNum : int16_t { N_DEBUG = -2, N_ABS = -1, N_UNDEF = 0 };
enum MagicNumber : uint16_t { XCOFF32 = 0x01DF, XCOFF64 = 0x01F7 };
+// Masks for packing/unpacking the r_rsize field of relocations.
+
+// The msb is used to indicate if the bits being relocated are signed or
+// unsigned.
+static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
+// The 2nd msb is used to indicate that the binder has replaced/modified the
+// original instruction.
+static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
+// The remaining bits specify the bit length of the relocatable reference
+// minus one.
+static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
+
// This field only exists in the XCOFF64 definition.
enum AuxHeaderFlags64 : uint16_t {
SHR_SYMTAB = 0x8000, ///< At exec time, create shared symbol table for program
diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h
index 9ef94f4420b5a..5a66c46ec840a 100644
--- a/llvm/include/llvm/Object/XCOFFObjectFile.h
+++ b/llvm/include/llvm/Object/XCOFFObjectFile.h
@@ -195,36 +195,8 @@ struct XCOFFSectionHeader64 : XCOFFSectionHeader<XCOFFSectionHeader64> {
char Padding[4];
};
-struct LoaderSectionHeader32 {
- support::ubig32_t Version;
- support::ubig32_t NumberOfSymTabEnt;
- support::ubig32_t NumberOfRelTabEnt;
- support::ubig32_t LengthOfImpidStrTbl;
- support::ubig32_t NumberOfImpid;
- support::big32_t OffsetToImpid;
- support::ubig32_t LengthOfStrTbl;
- support::big32_t OffsetToStrTbl;
-
- uint64_t getOffsetToSymTbl() const {
- return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32);
- }
-};
-
-struct LoaderSectionHeader64 {
- support::ubig32_t Version;
- support::ubig32_t NumberOfSymTabEnt;
- support::ubig32_t NumberOfRelTabEnt;
- support::ubig32_t LengthOfImpidStrTbl;
- support::ubig32_t NumberOfImpid;
- support::ubig32_t LengthOfStrTbl;
- support::big64_t OffsetToImpid;
- support::big64_t OffsetToStrTbl;
- support::big64_t OffsetToSymTbl;
- support::big64_t OffsetToRelEnt;
-
- uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; }
-};
-
+struct LoaderSectionHeader32;
+struct LoaderSectionHeader64;
struct LoaderSectionSymbolEntry32 {
struct NameOffsetInStrTbl {
support::big32_t IsNameInStrTbl; // Zero indicates name in string table.
@@ -256,6 +228,59 @@ struct LoaderSectionSymbolEntry64 {
getSymbolName(const LoaderSectionHeader64 *LoaderSecHeader) const;
};
+struct LoaderSectionRelocationEntry32 {
+ support::ubig32_t VirtualAddr;
+ support::big32_t SymbolIndex;
+ support::ubig16_t Type;
+ support::big16_t SectionNum;
+};
+
+struct LoaderSectionRelocationEntry64 {
+ support::ubig64_t VirtualAddr;
+ support::ubig16_t Type;
+ support::big16_t SectionNum;
+ support::big32_t SymbolIndex;
+};
+
+struct LoaderSectionHeader32 {
+ support::ubig32_t Version;
+ support::ubig32_t NumberOfSymTabEnt;
+ support::ubig32_t NumberOfRelTabEnt;
+ support::ubig32_t LengthOfImpidStrTbl;
+ support::ubig32_t NumberOfImpid;
+ support::big32_t OffsetToImpid;
+ support::ubig32_t LengthOfStrTbl;
+ support::big32_t OffsetToStrTbl;
+
+ uint64_t getOffsetToSymTbl() const {
+ return NumberOfSymTabEnt == 0 ? 0 : sizeof(LoaderSectionHeader32);
+ }
+
+ uint64_t getOffsetToRelEnt() const {
+ // Relocation table is after Symbol table.
+ return NumberOfRelTabEnt == 0
+ ? 0
+ : sizeof(LoaderSectionHeader32) +
+ sizeof(LoaderSectionSymbolEntry32) * NumberOfSymTabEnt;
+ }
+};
+
+struct LoaderSectionHeader64 {
+ support::ubig32_t Version;
+ support::ubig32_t NumberOfSymTabEnt;
+ support::ubig32_t NumberOfRelTabEnt;
+ support::ubig32_t LengthOfImpidStrTbl;
+ support::ubig32_t NumberOfImpid;
+ support::ubig32_t LengthOfStrTbl;
+ support::big64_t OffsetToImpid;
+ support::big64_t OffsetToStrTbl;
+ support::big64_t OffsetToSymTbl;
+ support::big64_t OffsetToRelEnt;
+
+ uint64_t getOffsetToSymTbl() const { return OffsetToSymTbl; }
+ uint64_t getOffsetToRelEnt() const { return OffsetToRelEnt; }
+};
+
template <typename AddressType> struct ExceptionSectionEntry {
union {
support::ubig32_t SymbolIdx;
@@ -468,20 +493,6 @@ struct XCOFFSectAuxEntForDWARF64 {
};
template <typename AddressType> struct XCOFFRelocation {
- // Masks for packing/unpacking the r_rsize field of relocations.
-
- // The msb is used to indicate if the bits being relocated are signed or
- // unsigned.
- static constexpr uint8_t XR_SIGN_INDICATOR_MASK = 0x80;
-
- // The 2nd msb is used to indicate that the binder has replaced/modified the
- // original instruction.
- static constexpr uint8_t XR_FIXUP_INDICATOR_MASK = 0x40;
-
- // The remaining bits specify the bit length of the relocatable reference
- // minus one.
- static constexpr uint8_t XR_BIASED_LENGTH_MASK = 0x3f;
-
public:
AddressType VirtualAddress;
support::ubig32_t SymbolIndex;
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation-invalid-sym-name.test b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation-invalid-sym-name.test
new file mode 100644
index 0000000000000..bedd92c746345
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation-invalid-sym-name.test
@@ -0,0 +1,39 @@
+## Test invalid offset to symbol string table of loader section for --loader-section-relocations option.
+
+# RUN: yaml2obj %s -o %t_xcoff.o
+# RUN: llvm-readobj --loader-section-relocations %t_xcoff.o 2>&1 | FileCheck -DFILE=%t_xcoff.o %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .loader
+ Flags: [ STYP_LOADER ]
+ SectionData: "0000000100000001000000020000016D00000001000000A40000000c0000005000000000000000A22000028000021105000000000000000020000294000000011f0000022000029c000000031f000002000a66756e63305f5f467600"
+## ^------- -Version=1
+## ^------- -NumberOfSymbolEntries=1
+## ^------- -NumberOfRelocationEntries=2
+## ^------- -LengthOfImportFileIDStringTable=365
+## ^------- -NumberOfImportFileIDs=1
+## ^------- -OffsetToImportFileIDs=0xA4
+## ^------- -LengthOfStringTable=12
+## ^------- -OffsetToStringTable=0x050
+## ^-------SymbolZero=0
+## ^-------OffsetToStringTbl=0xA2 (Invalid)
+## ^------- Value=0x20000280
+## ^--- sectionNumber = 2
+## ^- SymbolType=0x11
+## ^- StorageClass=0x05
+## ^------- ImportFileID=0
+## ^-------ParameterCheckType=0
+## ^------- Virtual Address = 0x20000294
+## ^------- SymbolIndex = 1
+## ^--- Type =0x1f
+## ^--- Section Num =2
+## ^------- Virtual Address = 0x20000294
+## ^------- SymbolIndex = 3
+## ^--- Type =0x1f
+## ^--- Section Num =2
+## ^StringTable
+
+# CHECK: warning: '[[FILE]]': entry with offset 0xa2 in the loader section's string table with size 0xc is invalid
diff --git a/llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation.test b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation.test
new file mode 100644
index 0000000000000..42eb897d07393
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/XCOFF/loader-section-relocation.test
@@ -0,0 +1,102 @@
+## Test the --loader-section-relocations option.
+
+# RUN: yaml2obj --docnum=1 %s -o %t_xcoff32.o
+# RUN: yaml2obj --docnum=2 %s -o %t_xcoff64.o
+# RUN: llvm-readobj --loader-section-relocations --expand-relocs %t_xcoff32.o | FileCheck --check-prefixes=COMMON,EXPAND %s
+# RUN: llvm-readobj --loader-section-relocations --expand-relocs %t_xcoff64.o | FileCheck --check-prefixes=COMMON,EXPAND %s
+# RUN: llvm-readobj --loader-section-relocations %t_xcoff32.o | FileCheck --check-prefixes=COMMON,NOEXPAND32 %s
+# RUN: llvm-readobj --loader-section-relocations %t_xcoff64.o | FileCheck --check-prefixes=COMMON,NOEXPAND64 %s
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1DF
+Sections:
+ - Name: .loader
+ Flags: [ STYP_LOADER ]
+ SectionData: "0000000100000001000000020000016D00000001000000A400000000000000506d79696e747661722000028000021105000000000000000020000294000000011f0000022000029c000000031f000002"
+## ^------- -Version=1
+## ^------- -NumberOfSymbolEntries=1
+## ^------- -NumberOfRelocationEntries=2
+## ^------- -LengthOfImportFileIDStringTable=365
+## ^------- -NumberOfImportFileIDs=1
+## ^------- -OffsetToImportFileIDs=0xA4
+## ^------- -LengthOfStringTable=0
+## ^------- -OffsetToStringTable=0
+## ^--------------- SymbolName=myintvar
+## ^------- Value=0x20000280
+## ^--- sectionNumber = 2
+## ^- SymbolType=0x11
+## ^- StorageClass=0x05
+## ^------- ImportFileID=0
+## ^-------ParameterCheckType=0
+## ^------- Virtual Address = 0x20000294
+## ^------- SymbolIndex = 1
+## ^--- Type =0x1f00
+## ^--- Section Num =2
+## ^------- Virtual Address = 0x20000294
+## ^------- SymbolIndex = 3
+## ^--- Type =0x1f00
+## ^--- Section Num =2
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x1F7
+Sections:
+ - Name: .loader
+ Flags: [ STYP_LOADER ]
+ SectionData: "0000000200000001000000020000016D000000010000001200000000000000D000000000000000700000000000000038000000000000005000000001100003000000000200021105000000000000000000000000200002941f00000200000001000000002000029C1f0000020000000300096d79696e747661720000"
+## ^------- -Version=2
+## ^------- -NumberOfSymbolEntries=1
+## ^------- -NumberOfRelocationEntries=2
+## ^------- -LengthOfImportFileIDStringTable=365
+## ^------- -NumberOfImportFileIDs=1
+## ^------- --LengthOfStringTable=0x12
+## ^--------------- -OffsetToImportFileIDs=0xD0
+## ^--------------- -OffsetToStringTable=0x70
+## ^--------------- -OffsetToSymbolTable=0x38
+## ^--------------- -OffsetToRelocationEntries=0x50
+## ^--------------- Value=0x0000000110000300
+## ^------- OffsetToStringTbl=2
+## ^--- sectionNumber = 2
+## ^- SymbolType=0x11
+## ^- StorageClass=0x05
+## ^------- ImportFileID=0
+## ^-------ParameterCheckType=0
+## ^--------------- VirtualAddress= 0x20000294
+## ^--- Type= 1f00
+## ^---SectionNumber = 2
+## ^------- SymbolIndex =1
+## ^--------------- VirtualAddress= 0x2000029C
+## ^--- Type= 1f00
+## ^---SectionNumber = 2
+## ^------- SymbolIndex =3
+## ^-------------------StringTable
+
+# COMMON: Loader Section {
+# COMMON-NEXT: Loader Section Relocations {
+# NOEXPAND64-NEXT: Vaddr Type SecNum SymbolName (Index)
+# NOEXPAND64-NEXT: 0x0000000020000294 0x1f00 (R_POS) 2 .data (1)
+# NOEXPAND64-NEXT: 0x000000002000029c 0x1f00 (R_POS) 2 myintvar (3)
+# NOEXPAND32-NEXT: Vaddr Type SecNum SymbolName (Index)
+# NOEXPAND32-NEXT: 0x20000294 0x1f00 (R_POS) 2 .data (1)
+# NOEXPAND32-NEXT: 0x2000029c 0x1f00 (R_POS) 2 myintvar (3)
+# EXPAND-NEXT: Relocation {
+# EXPAND-NEXT: Virtual Address: 0x20000294
+# EXPAND-NEXT: Symbol: .data (1)
+# EXPAND-NEXT: IsSigned: No
+# EXPAND-NEXT: FixupBitValue: 0
+# EXPAND-NEXT: Length: 32
+# EXPAND-NEXT: Type: R_POS (0x0)
+# EXPAND-NEXT: SectionNumber: 2
+# EXPAND-NEXT: }
+# EXPAND-NEXT: Relocation {
+# EXPAND-NEXT: Virtual Address: 0x2000029C
+# EXPAND-NEXT: Symbol: myintvar (3)
+# EXPAND-NEXT: IsSigned: No
+# EXPAND-NEXT: FixupBitValue: 0
+# EXPAND-NEXT: Length: 32
+# EXPAND-NEXT: Type: R_POS (0x0)
+# EXPAND-NEXT: SectionNumber: 2
+# EXPAND-NEXT: }
+# EXPAND-NEXT: }
+# EXPAND-NEXT: }
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index c7d3dd030a1ed..4a2c2950578c6 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -155,10 +155,12 @@ class ObjDumper {
llvm::codeview::GlobalTypeTableBuilder &GlobalCVTypes,
bool GHash) {}
- // Only implement for XCOFF
+ // Only implemented for XCOFF.
+ virtual void printStringTable() {}
virtual void printAuxiliaryHeader() {}
virtual void printExceptionSection() {}
- virtual void printLoaderSection(bool PrintHeader, bool PrintSymbolTable) {}
+ virtual void printLoaderSection(bool PrintHeader, bool PrintSymbols,
+ bool PrintRelocations) {}
// Only implemented for MachO.
virtual void printMachODataInCode() { }
@@ -168,9 +170,6 @@ class ObjDumper {
virtual void printMachOIndirectSymbols() { }
virtual void printMachOLinkerOptions() { }
- // Currently only implemented for XCOFF.
- virtual void printStringTable() { }
-
virtual void printStackMap() const = 0;
void printAsStringList(StringRef StringContent, size_t StringDataOffset = 0);
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 7d0e64ad42c04..4f7b12f95a60a 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -91,6 +91,7 @@ def auxiliary_header : FF<"auxiliary-header" , "Display the auxiliary header">,
def exception_section : FF<"exception-section" , "Display the exception section entries">, Group<grp_xcoff>;
def loader_section_header : FF<"loader-section-header" , "Display the loader section header">, Group<grp_xcoff>;
def loader_section_symbols : FF<"loader-section-symbols" , "Display the loader section symbol table">, Group<grp_xcoff>;
+def loader_section_relocations : FF<"loader-section-relocations" , "Display the loader section relocation entries">, Group<grp_xcoff>;
def help : FF<"help", "Display this help">;
def version : FF<"version", "Display the version">;
diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index 2556f860fb50c..34ba6df00b931 100644
--- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -40,7 +40,8 @@ class XCOFFDumper : public ObjDumper {
void printNeededLibraries() override;
void printStringTable() override;
void printExceptionSection() override;
- void printLoaderSection(bool PrintHeader, bool PrintSymbolTable) override;
+ void printLoaderSection(bool PrintHeader, bool PrintSymbols,
+ bool PrintRelocations) override;
ScopedPrinter &getScopedPrinter() const { return W; }
@@ -71,7 +72,16 @@ class XCOFFDumper : public ObjDumper {
void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);
template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);
+ template <typename LoadSectionRelocTy>
+ void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,
+ StringRef SymbolName);
+ void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);
+ template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
+ typename LoaderSectionRelocationEntry>
+ void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);
+
const XCOFFObjectFile &Obj;
+ const static int32_t FirstSymIdxOfLoaderSec = 3;
};
} // anonymous namespace
@@ -138,7 +148,8 @@ void XCOFFDumper::printSectionHeaders() {
printSectionHeaders(Obj.sections32());
}
-void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbolTable) {
+void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,
+ bool PrintRelocations) {
DictScope DS(W, "Loader Section");
Expected<uintptr_t> LoaderSectionAddrOrError =
Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
@@ -155,13 +166,12 @@ void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbolTable) {
if (PrintHeader)
printLoaderSectionHeader(LoaderSectionAddr);
- if (PrintSymbolTable)
+ if (PrintSymbols)
printLoaderSectionSymbols(LoaderSectionAddr);
- // TODO: Need to add printing of relocation entry of loader section later.
- // For example:
- // if (PrintRelocation)
- // printLoaderSectionRelocationEntry();
+ if (PrintRelocations)
+ printLoaderSectionRelocationEntries(LoaderSectionAddr);
+
W.unindent();
}
@@ -261,6 +271,140 @@ void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {
LoaderSectionHeader32>(LoaderSectionAddr);
}
+const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
+#define ECase(X) \
+ { #X, XCOFF::X }
+ ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
+ ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
+ ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
+ ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
+ ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
+ ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
+#undef ECase
+};
+
+// From the XCOFF specification: there are five implicit external symbols, one
+// each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
+// are referenced from the relocation table entries using symbol table index
+// values 0, 1, 2, -1, and -2, respectively.
+static const char *getImplicitLoaderSectionSymName(int SymIndx) {
+ switch (SymIndx) {
+ default:
+ return "Unkown Symbol Name";
+ case -2:
+ return ".tbss";
+ case -1:
+ return ".tdata";
+ case 0:
+ return ".text";
+ case 1:
+ return ".data";
+ case 2:
+ return ".bss";
+ }
+}
+
+template <typename LoadSectionRelocTy>
+void XCOFFDumper::printLoaderSectionRelocationEntry(
+ LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {
+ uint16_t Type = LoaderSecRelEntPtr->Type;
+ if (opts::ExpandRelocs) {
+ DictScope DS(W, "Relocation");
+ auto IsRelocationSigned = [](uint8_t Info) {
+ return Info & XCOFF::XR_SIGN_INDICATOR_MASK;
+ };
+ auto IsFixupIndicated = [](uint8_t Info) {
+ return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;
+ };
+ auto GetRelocatedLength = [](uint8_t Info) {
+ // The relocation encodes the bit length being relocated minus 1. Add
+ // back
+ // the 1 to get the actual length being relocated.
+ return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;
+ };
+
+ uint8_t Info = Type >> 8;
+ W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);
+ W.printNumber("Symbol", SymbolName, LoaderSecRelEntPtr->SymbolIndex);
+ W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");
+ W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);
+ W.printNumber("Length", GetRelocatedLength(Info));
+ W.printEnum("Type", static_cast<uint8_t>(Type),
+ makeArrayRef(RelocationTypeNameclass));
+ W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);
+ } else {
+ W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,
+ Obj.is64Bit() ? 18 : 10)
+ << " " << format_hex(Type, 6) << " ("
+ << XCOFF::getRelocationTypeString(
+ static_cast<XCOFF::RelocationType>(Type))
+ << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)
+ << " " << SymbolName << " ("
+ << LoaderSecRelEntPtr->SymbolIndex << ")\n";
+ }
+}
+
+template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
+ typename LoaderSectionRelocationEntry>
+void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
+ uintptr_t LoaderSectionAddr) {
+ const LoaderSectionHeader *LoaderSec =
+ reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
+ const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =
+ reinterpret_cast<const LoaderSectionRelocationEntry *>(
+ LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));
+
+ if (!opts::ExpandRelocs)
+ W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)
+ << center_justify("Type", 15) << right_justify("SecNum", 8)
+ << center_justify("SymbolName (Index) ", 24) << "\n";
+
+ for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;
+ ++i, ++LoaderSecRelEntPtr) {
+ StringRef SymbolName;
+ if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {
+ // Because there are implicit symbol index values (-2, -1, 0, 1, 2),
+ // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
+ // real symbol from the symbol table.
+ const uint64_t SymOffset =
+ (LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *
+ sizeof(LoaderSectionSymbolEntry);
+ const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =
+ reinterpret_cast<LoaderSectionSymbolEntry *>(
+ LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +
+ SymOffset);
+
+ Expected<StringRef> SymbolNameOrErr =
+ LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);
+ if (!SymbolNameOrErr) {
+ reportUniqueWarning(SymbolNameOrErr.takeError());
+ return;
+ }
+ SymbolName = SymbolNameOrErr.get();
+ } else
+ SymbolName =
+ getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);
+
+ printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);
+ }
+}
+
+void XCOFFDumper::printLoaderSectionRelocationEntries(
+ uintptr_t LoaderSectionAddr) {
+ DictScope DS(W, "Loader Section Relocations");
+
+ if (Obj.is64Bit())
+ printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,
+ LoaderSectionSymbolEntry64,
+ LoaderSectionRelocationEntry64>(
+ LoaderSectionAddr);
+ else
+ printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,
+ LoaderSectionSymbolEntry32,
+ LoaderSectionRelocationEntry32>(
+ LoaderSectionAddr);
+}
+
template <typename T>
void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
if (ExceptionSectEnt.getReason())
@@ -309,18 +453,6 @@ void XCOFFDumper::printRelocations() {
printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
}
-const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
-#define ECase(X) \
- { #X, XCOFF::X }
- ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
- ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
- ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
- ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
- ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
- ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
-#undef ECase
-};
-
template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
Expected<StringRef> ErrOrSymbolName =
Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index b618b4f5ba188..15a6c68bdebea 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -164,6 +164,7 @@ static bool COFFTLSDirectory;
static bool XCOFFAuxiliaryHeader;
static bool XCOFFLoaderSectionHeader;
static bool XCOFFLoaderSectionSymbol;
+static bool XCOFFLoaderSectionRelocation;
static bool XCOFFExceptionSection;
OutputStyleTy Output = OutputStyleTy::LLVM;
@@ -307,6 +308,8 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header);
opts::XCOFFLoaderSectionSymbol = Args.hasArg(OPT_loader_section_symbols);
+ opts::XCOFFLoaderSectionRelocation =
+ Args.hasArg(OPT_loader_section_relocations);
opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section);
opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
@@ -512,9 +515,11 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
}
if (Obj.isXCOFF()) {
- if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol)
+ if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol ||
+ opts::XCOFFLoaderSectionRelocation)
Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader,
- opts::XCOFFLoaderSectionSymbol);
+ opts::XCOFFLoaderSectionSymbol,
+ opts::XCOFFLoaderSectionRelocation);
if (opts::XCOFFExceptionSection)
Dumper->printExceptionSection();
More information about the llvm-commits
mailing list