[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