[llvm] r374946 - [XCOFF]implement parsing relocation information for 32-bit xcoff object file

Digger Lin via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 13:42:12 PDT 2019


Author: diggerlin
Date: Tue Oct 15 13:42:11 2019
New Revision: 374946

URL: http://llvm.org/viewvc/llvm-project?rev=374946&view=rev
Log:
[XCOFF]implement parsing relocation information for 32-bit xcoff object file

Summary:
    Parsing the relocation entry information for 32-bit xcoff object file
including deal with the relocation overflow.

Reviewers: hubert.reinterpretcast, jasonliu, sfertile, xingxue.

Subscribers: hiraditya, rupprecht, seiya

Differential Revision: https://reviews.llvm.org/D67008

Added:
    llvm/trunk/test/tools/llvm-readobj/reloc_overflow.test
Modified:
    llvm/trunk/include/llvm/BinaryFormat/XCOFF.h
    llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
    llvm/trunk/lib/Object/XCOFFObjectFile.cpp
    llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test
    llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp

Modified: llvm/trunk/include/llvm/BinaryFormat/XCOFF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/XCOFF.h?rev=374946&r1=374945&r2=374946&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/XCOFF.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/XCOFF.h Tue Oct 15 13:42:11 2019
@@ -148,6 +148,68 @@ enum SymbolType {
   XTY_CM = 3  ///< Common csect definition. For uninitialized storage.
 };
 
+// Relocation types, defined in `/usr/include/reloc.h`.
+enum RelocationType : uint8_t {
+  R_POS = 0x00, ///< Positive relocation. Provides the address of the referenced
+                ///< symbol.
+  R_RL = 0x0c,  ///< Positive indirect load relocation. Modifiable instruction.
+  R_RLA = 0x0d, ///< Positive load address relocation. Modifiable instruction.
+
+  R_NEG = 0x01, ///< Negative relocation. Provides the negative of the address
+                ///< of the referenced symbol.
+  R_REL = 0x02, ///< Relative to self relocation. Provides a displacement value
+                ///< between the address of the referenced symbol and the
+                ///< address being relocated.
+
+  R_TOC = 0x03, ///< Relative to the TOC relocation. Provides a displacement
+                ///< that is the difference between the address of the
+                ///< referenced symbol and the TOC anchor csect.
+  R_TRL = 0x12, ///< TOC relative indirect load relocation. Similar to R_TOC,
+                ///< but not modifiable instruction.
+
+  R_TRLA =
+      0x13, ///< Relative to the TOC or to the thread-local storage base
+            ///< relocation. Compilers are not permitted to generate this
+            ///< relocation type. It is the result of a reversible
+            ///< transformation by the linker of an R_TOC relation that turned a
+            ///< load instruction into an add-immediate instruction.
+
+  R_GL = 0x05, ///< Global linkage-external TOC address relocation. Provides the
+               ///< address of the external TOC associated with a defined
+               ///< external symbol.
+  R_TCL = 0x06, ///< Local object TOC address relocation. Provides the address
+                ///< of the local TOC entry of a defined external symbol.
+
+  R_REF = 0x0f, ///< A non-relocating relocation. Used to prevent the binder
+                ///< from garbage collecting a csect (such as code used for
+                ///< dynamic initialization of non-local statics) for which
+                ///< another csect has an implicit dependency.
+
+  R_BA = 0x08, ///< Branch absolute relocation. Provides the address of the
+               ///< referenced symbol. References a non-modifiable instruction.
+  R_BR = 0x0a, ///< Branch relative to self relocation. Provides the
+               ///< displacement that is the difference between the address of
+               ///< the referenced symbol and the address of the referenced
+               ///< branch instruction. References a non-modifiable instruction.
+  R_RBA = 0x18, ///< Branch absolute relocation. Similar to R_BA but
+                ///< references a modifiable instruction.
+  R_RBR = 0x1a, ///< Branch relative to self relocation. Similar to the R_BR
+                ///< relocation type, but references a modifiable instruction.
+
+  R_TLS = 0x20,    ///< General-dynamic reference to TLS symbol.
+  R_TLS_IE = 0x21, ///< Initial-exec reference to TLS symbol.
+  R_TLS_LD = 0x22, ///< Local-dynamic reference to TLS symbol.
+  R_TLS_LE = 0x23, ///< Local-exec reference to TLS symbol.
+  R_TLSM = 0x24,  ///< Module reference to TLS. Provides a handle for the module
+                  ///< containing the referenced symbol.
+  R_TLSML = 0x25, ///< Module reference to the local TLS storage.
+
+  R_TOCU = 0x30, ///< Relative to TOC upper. Specifies the high-order 16 bits of
+                 ///< a large code model TOC-relative relocation.
+  R_TOCL = 0x31 ///< Relative to TOC lower. Specifies the low-order 16 bits of a
+                ///< large code model TOC-relative relocation.
+};
+
 struct FileHeader32 {
   uint16_t Magic;
   uint16_t NumberOfSections;

Modified: llvm/trunk/include/llvm/Object/XCOFFObjectFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/XCOFFObjectFile.h?rev=374946&r1=374945&r2=374946&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/XCOFFObjectFile.h (original)
+++ llvm/trunk/include/llvm/Object/XCOFFObjectFile.h Tue Oct 15 13:42:11 2019
@@ -149,6 +149,38 @@ struct XCOFFSectAuxEntForStat {
   uint8_t Pad[10];
 };
 
+struct XCOFFRelocation32 {
+  // 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:
+  support::ubig32_t VirtualAddress;
+  support::ubig32_t SymbolIndex;
+
+  // Packed field, see XR_* masks for details of packing.
+  uint8_t Info;
+
+  XCOFF::RelocationType Type;
+
+public:
+  bool isRelocationSigned() const;
+  bool isFixupIndicated() const;
+
+  // Returns the number of bits being relocated.
+  uint8_t getRelocatedLength() const;
+};
+
 class XCOFFObjectFile : public ObjectFile {
 private:
   const void *FileHeader = nullptr;
@@ -278,6 +310,7 @@ public:
 
   uint32_t getNumberOfSymbolTableEntries64() const;
   uint32_t getSymbolIndex(uintptr_t SymEntPtr) const;
+  Expected<StringRef> getSymbolNameByIndex(uint32_t SymbolTableIndex) const;
 
   Expected<StringRef> getCFileName(const XCOFFFileAuxEnt *CFileEntPtr) const;
   uint16_t getOptionalHeaderSize() const;
@@ -291,6 +324,13 @@ public:
   Expected<DataRefImpl> getSectionByNum(int16_t Num) const;
 
   void checkSymbolEntryPointer(uintptr_t SymbolEntPtr) const;
+
+  // Relocation-related interfaces.
+  Expected<uint32_t>
+  getLogicalNumberOfRelocationEntries(const XCOFFSectionHeader32 &Sec) const;
+
+  Expected<ArrayRef<XCOFFRelocation32>>
+  relocations(const XCOFFSectionHeader32 &) const;
 }; // XCOFFObjectFile
 
 class XCOFFSymbolRef {

Modified: llvm/trunk/lib/Object/XCOFFObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/XCOFFObjectFile.cpp?rev=374946&r1=374945&r2=374946&view=diff
==============================================================================
--- llvm/trunk/lib/Object/XCOFFObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/XCOFFObjectFile.cpp Tue Oct 15 13:42:11 2019
@@ -17,10 +17,7 @@
 namespace llvm {
 namespace object {
 
-enum {
-  FUNCTION_SYM = 0x20,
-  SYM_TYPE_MASK = 0x07
-};
+enum { FUNCTION_SYM = 0x20, SYM_TYPE_MASK = 0x07, RELOC_OVERFLOW = 65535 };
 
 // Checks that [Ptr, Ptr + Size) bytes fall inside the memory buffer
 // 'M'. Returns a pointer to the underlying object on success.
@@ -49,6 +46,20 @@ static StringRef generateXCOFFFixedNameS
                     : StringRef(Name, XCOFF::NameSize);
 }
 
+bool XCOFFRelocation32::isRelocationSigned() const {
+  return Info & XR_SIGN_INDICATOR_MASK;
+}
+
+bool XCOFFRelocation32::isFixupIndicated() const {
+  return Info & XR_FIXUP_INDICATOR_MASK;
+}
+
+uint8_t XCOFFRelocation32::getRelocatedLength() const {
+  // The relocation encodes the bit length being relocated minus 1. Add back
+  // the 1 to get the actual length being relocated.
+  return (Info & XR_BIASED_LENGTH_MASK) + 1;
+}
+
 void XCOFFObjectFile::checkSectionAddress(uintptr_t Addr,
                                           uintptr_t TableAddress) const {
   if (Addr < TableAddress)
@@ -494,6 +505,19 @@ uint32_t XCOFFObjectFile::getSymbolIndex
          XCOFF::SymbolTableEntrySize;
 }
 
+Expected<StringRef>
+XCOFFObjectFile::getSymbolNameByIndex(uint32_t Index) const {
+  if (is64Bit())
+    report_fatal_error("64-bit symbol table support not implemented yet.");
+
+  if (Index >= getLogicalNumberOfSymbolTableEntries32())
+    return errorCodeToError(object_error::invalid_symbol_index);
+
+  DataRefImpl SymDRI;
+  SymDRI.p = reinterpret_cast<uintptr_t>(getPointerToSymbolTable() + Index);
+  return getSymbolName(SymDRI);
+}
+
 uint16_t XCOFFObjectFile::getFlags() const {
   return is64Bit() ? fileHeader64()->Flags : fileHeader32()->Flags;
 }
@@ -529,6 +553,46 @@ ArrayRef<XCOFFSectionHeader32> XCOFFObje
                                         TablePtr + getNumberOfSections());
 }
 
+// In an XCOFF32 file, when the field value is 65535, then an STYP_OVRFLO
+// section header contains the actual count of relocation entries in the s_paddr
+// field. STYP_OVRFLO headers contain the section index of their corresponding
+// sections as their raw "NumberOfRelocations" field value.
+Expected<uint32_t> XCOFFObjectFile::getLogicalNumberOfRelocationEntries(
+    const XCOFFSectionHeader32 &Sec) const {
+
+  uint16_t SectionIndex = &Sec - sectionHeaderTable32() + 1;
+
+  if (Sec.NumberOfRelocations < RELOC_OVERFLOW)
+    return Sec.NumberOfRelocations;
+  for (const auto &Sec : sections32()) {
+    if (Sec.Flags == XCOFF::STYP_OVRFLO &&
+        Sec.NumberOfRelocations == SectionIndex)
+      return Sec.PhysicalAddress;
+  }
+  return errorCodeToError(object_error::parse_failed);
+}
+
+Expected<ArrayRef<XCOFFRelocation32>>
+XCOFFObjectFile::relocations(const XCOFFSectionHeader32 &Sec) const {
+  uintptr_t RelocAddr = getWithOffset(reinterpret_cast<uintptr_t>(FileHeader),
+                                      Sec.FileOffsetToRelocationInfo);
+  auto NumRelocEntriesOrErr = getLogicalNumberOfRelocationEntries(Sec);
+  if (Error E = NumRelocEntriesOrErr.takeError())
+    return std::move(E);
+
+  uint32_t NumRelocEntries = NumRelocEntriesOrErr.get();
+
+  auto RelocationOrErr =
+      getObject<XCOFFRelocation32>(Data, reinterpret_cast<void *>(RelocAddr),
+                                   NumRelocEntries * sizeof(XCOFFRelocation32));
+  if (Error E = RelocationOrErr.takeError())
+    return std::move(E);
+
+  const XCOFFRelocation32 *StartReloc = RelocationOrErr.get();
+
+  return ArrayRef<XCOFFRelocation32>(StartReloc, StartReloc + NumRelocEntries);
+}
+
 Expected<XCOFFStringTable>
 XCOFFObjectFile::parseStringTable(const XCOFFObjectFile *Obj, uint64_t Offset) {
   // If there is a string table, then the buffer must contain at least 4 bytes

Added: llvm/trunk/test/tools/llvm-readobj/reloc_overflow.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/reloc_overflow.test?rev=374946&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/reloc_overflow.test (added)
+++ llvm/trunk/test/tools/llvm-readobj/reloc_overflow.test Tue Oct 15 13:42:11 2019
@@ -0,0 +1,80 @@
+# RUN: llvm-readobj --sections %p/Inputs/xcoff-reloc-overflow.o | \
+# RUN: FileCheck --check-prefix=SECOVERFLOW %s
+
+# RUN: llvm-readobj --relocs --expand-relocs %p/Inputs/xcoff-reloc-overflow.o | \
+# RUN: FileCheck --check-prefix=RELOCOVERFLOW %s
+
+# SECOVERFLOW:      File: {{.*}}xcoff-reloc-overflow.o
+# SECOVERFLOW-NEXT: Format: aixcoff-rs6000
+# SECOVERFLOW-NEXT: Arch: powerpc
+# SECOVERFLOW-NEXT: AddressSize: 32bit
+# SECOVERFLOW-NEXT: Sections [
+# SECOVERFLOW-NEXT:   Section {
+# SECOVERFLOW-NEXT:     Index: 1
+# SECOVERFLOW-NEXT:     Name: .text
+# SECOVERFLOW-NEXT:     PhysicalAddress: 0x0
+# SECOVERFLOW-NEXT:     VirtualAddress: 0x0
+# SECOVERFLOW-NEXT:     Size: 0x38
+# SECOVERFLOW-NEXT:     RawDataOffset: 0x8C
+# SECOVERFLOW-NEXT:     RelocationPointer: 0x0
+# SECOVERFLOW-NEXT:     LineNumberPointer: 0x0
+# SECOVERFLOW-NEXT:     NumberOfRelocations: 0
+# SECOVERFLOW-NEXT:     NumberOfLineNumbers: 0
+# SECOVERFLOW-NEXT:     Type: STYP_TEXT (0x20)
+# SECOVERFLOW-NEXT:   }
+# SECOVERFLOW-NEXT:   Section {
+# SECOVERFLOW-NEXT:     Index: 2
+# SECOVERFLOW-NEXT:     Name: .data
+# SECOVERFLOW-NEXT:     PhysicalAddress: 0x38
+# SECOVERFLOW-NEXT:     VirtualAddress: 0x38
+# SECOVERFLOW-NEXT:     Size: 0x1C
+# SECOVERFLOW-NEXT:     RawDataOffset: 0xC4
+# SECOVERFLOW-NEXT:     RelocationPointer: 0xE0
+# SECOVERFLOW-NEXT:     LineNumberPointer: 0x0
+# SECOVERFLOW-NEXT:     NumberOfRelocations: 65535
+# SECOVERFLOW-NEXT:     NumberOfLineNumbers: 65535
+# SECOVERFLOW-NEXT:     Type: STYP_DATA (0x40)
+# SECOVERFLOW-NEXT:   }
+# SECOVERFLOW-NEXT:   Section {
+# SECOVERFLOW-NEXT:     Index: 3
+# SECOVERFLOW-NEXT:     Name: .ovrflo
+# SECOVERFLOW-NEXT:     NumberOfRelocations: 3
+# SECOVERFLOW-NEXT:     NumberOfLineNumbers: 3
+# SECOVERFLOW-NEXT:     Size: 0x0
+# SECOVERFLOW-NEXT:     RawDataOffset: 0x0
+# SECOVERFLOW-NEXT:     RelocationPointer: 0xE0
+# SECOVERFLOW-NEXT:     LineNumberPointer: 0x0
+# SECOVERFLOW-NEXT:     IndexOfSectionOverflowed: 2
+# SECOVERFLOW-NEXT:     IndexOfSectionOverflowed: 2
+# SECOVERFLOW-NEXT:     Type: STYP_OVRFLO (0x8000)
+# SECOVERFLOW-NEXT:   }
+# SECOVERFLOW-NEXT: ]
+
+# RELOCOVERFLOW: Relocations [
+# RELOCOVERFLOW-NEXT:   Section (index: 2) .data {
+# RELOCOVERFLOW-NEXT:   Relocation {
+# RELOCOVERFLOW-NEXT:     Virtual Address: 0x38
+# RELOCOVERFLOW-NEXT:     Symbol: .pb (4)
+# RELOCOVERFLOW-NEXT:     IsSigned: No
+# RELOCOVERFLOW-NEXT:     FixupBitValue: 0
+# RELOCOVERFLOW-NEXT:     Length: 32
+# RELOCOVERFLOW-NEXT:     Type: R_POS (0x0)
+# RELOCOVERFLOW-NEXT:   }
+# RELOCOVERFLOW-NEXT:   Relocation {
+# RELOCOVERFLOW-NEXT:     Virtual Address: 0x3C
+# RELOCOVERFLOW-NEXT:     Symbol: TOC (12)
+# RELOCOVERFLOW-NEXT:     IsSigned: No
+# RELOCOVERFLOW-NEXT:     FixupBitValue: 0
+# RELOCOVERFLOW-NEXT:     Length: 32
+# RELOCOVERFLOW-NEXT:     Type: R_POS (0x0)
+# RELOCOVERFLOW-NEXT:   }
+# RELOCOVERFLOW-NEXT:   Relocation {
+# RELOCOVERFLOW-NEXT:     Virtual Address: 0x50
+# RELOCOVERFLOW-NEXT:     Symbol: .text (2)
+# RELOCOVERFLOW-NEXT:     IsSigned: No
+# RELOCOVERFLOW-NEXT:     FixupBitValue: 0
+# RELOCOVERFLOW-NEXT:     Length: 32
+# RELOCOVERFLOW-NEXT:     Type: R_POS (0x0)
+# RELOCOVERFLOW-NEXT:   }
+# RELOCOVERFLOW-NEXT: }
+# RELOCOVERFLOW-NEXT: ]

Modified: llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test?rev=374946&r1=374945&r2=374946&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/xcoff-basic.test Tue Oct 15 13:42:11 2019
@@ -10,6 +10,9 @@
 # RUN: llvm-readobj --file-header %p/Inputs/xcoff-basic-neg-sym-count.o | \
 # RUN: FileCheck --check-prefix=NEGSYMCOUNT %s
 
+# RUN: llvm-readobj --relocs --expand-relocs %p/Inputs/xcoff-basic.o | \
+# RUN: FileCheck --check-prefix=RELOCSEXP %s
+
 # FILEHEADER:     File: {{.*}}xcoff-basic.o
 # FILEHEADER-NEXT: Format: aixcoff-rs6000
 # FILEHEADER-NEXT: Arch: powerpc
@@ -81,3 +84,77 @@
 # xcoff-basic-neg-sym-count.o was stripped using the 'strip' utility, and
 # manually edited to have a negative symbol table entry count.
 
+# RELOCSEXP: File: {{.*}}xcoff-basic.o
+# RELOCSEXP-NEXT: Format: aixcoff-rs6000
+# RELOCSEXP-NEXT: Arch: powerpc
+# RELOCSEXP-NEXT: AddressSize: 32bit
+# RELOCSEXP-NEXT: Relocations [
+# RELOCSEXP-NEXT:  Section (index: 1) .text {
+# RELOCSEXP-NEXT:    Relocation {
+# RELOCSEXP-NEXT:      Virtual Address: 0x2
+# RELOCSEXP-NEXT:      Symbol: a (85)
+# RELOCSEXP-NEXT:      IsSigned: Yes
+# RELOCSEXP-NEXT:      FixupBitValue: 0
+# RELOCSEXP-NEXT:      Length: 16
+# RELOCSEXP-NEXT:      Type: R_TOC (0x3)
+# RELOCSEXP-NEXT:    }
+
+# RELOCSEXP:           Virtual Address: 0x90
+# RELOCSEXP-NEXT:      Symbol: .__tls_get_addr (118)
+# RELOCSEXP-NEXT:      IsSigned: Yes
+# RELOCSEXP-NEXT:      FixupBitValue: 0
+# RELOCSEXP-NEXT:      Length: 26
+# RELOCSEXP-NEXT:      Type: R_RBA (0x18)
+# RELOCSEXP-NEXT:    }
+# RELOCSEXP-NEXT:  }
+# RELOCSEXP-NEXT:  Section (index: 2) .data {
+# RELOCSEXP-NEXT:    Relocation {
+# RELOCSEXP-NEXT:      Virtual Address: 0x100
+# RELOCSEXP-NEXT:      Symbol: A (78)
+# RELOCSEXP-NEXT:      IsSigned: No
+# RELOCSEXP-NEXT:      FixupBitValue: 0
+# RELOCSEXP-NEXT:      Length: 32
+# RELOCSEXP-NEXT:      Type: R_POS (0x0)
+# RELOCSEXP-NEXT:    }
+
+# RELOCSEXP:           Virtual Address: 0x110
+# RELOCSEXP-NEXT:      Symbol: J (96)
+# RELOCSEXP-NEXT:      IsSigned: No
+# RELOCSEXP-NEXT:      FixupBitValue: 0
+# RELOCSEXP-NEXT:      Length: 32
+# RELOCSEXP-NEXT:      Type: R_POS (0x0)
+# RELOCSEXP-NEXT:    }
+
+# RELOCSEXP:          Virtual Address: 0x114
+# RELOCSEXP-NEXT:     Symbol: j (100)
+# RELOCSEXP-NEXT:     IsSigned: No
+# RELOCSEXP-NEXT:     FixupBitValue: 0
+# RELOCSEXP-NEXT:     Length: 32
+# RELOCSEXP-NEXT:     Type: R_TLS (0x20)
+# RELOCSEXP-NEXT:    }
+
+# RELOCSEXP:          Virtual Address: 0x124
+# RELOCSEXP-NEXT:     Symbol: d (111)
+# RELOCSEXP-NEXT:     IsSigned: No
+# RELOCSEXP-NEXT:     FixupBitValue: 0
+# RELOCSEXP-NEXT:     Length: 32
+# RELOCSEXP-NEXT:     Type: R_TLSM (0x24)
+# RELOCSEXP-NEXT:    }
+
+# RELOCSEXP:           Virtual Address: 0x128
+# RELOCSEXP-NEXT:      Symbol: (76)
+# RELOCSEXP-NEXT:      IsSigned: No
+# RELOCSEXP-NEXT:      FixupBitValue: 0
+# RELOCSEXP-NEXT:      Length: 32
+# RELOCSEXP-NEXT:      Type: R_POS (0x0)
+# RELOCSEXP-NEXT:    }
+
+# RELOCSEXP:           Virtual Address: 0x154
+# RELOCSEXP-NEXT:      Symbol: TOC (72)
+# RELOCSEXP-NEXT:      IsSigned: No
+# RELOCSEXP-NEXT:      FixupBitValue: 0
+# RELOCSEXP-NEXT:      Length: 32
+# RELOCSEXP-NEXT:      Type: R_POS (0x0)
+# RELOCSEXP-NEXT:    }
+# RELOCSEXP-NEXT:  }
+# RELOCSEXP-NEXT:]

Modified: llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp?rev=374946&r1=374945&r2=374946&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/XCOFFDumper.cpp Tue Oct 15 13:42:11 2019
@@ -56,6 +56,7 @@ private:
   // The low order 16 bits of section flags denotes the section type.
   static constexpr unsigned SectionFlagsTypeMask = 0xffffu;
 
+  void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
   const XCOFFObjectFile &Obj;
 };
 } // anonymous namespace
@@ -115,7 +116,58 @@ void XCOFFDumper::printSectionHeaders()
 }
 
 void XCOFFDumper::printRelocations() {
-  llvm_unreachable("Unimplemented functionality for XCOFFDumper");
+  if (Obj.is64Bit())
+    llvm_unreachable("64-bit relocation output not implemented!");
+  else
+    printRelocations(Obj.sections32());
+}
+
+static 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
+};
+
+void XCOFFDumper::printRelocations(ArrayRef<XCOFFSectionHeader32> Sections) {
+  if (!opts::ExpandRelocs)
+    report_fatal_error("Unexpanded relocation output not implemented.");
+
+  ListScope LS(W, "Relocations");
+  uint16_t Index = 0;
+  for (const auto &Sec : Sections) {
+    ++Index;
+    // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
+    if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
+        Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
+      continue;
+    auto Relocations = unwrapOrError(Obj.getFileName(), Obj.relocations(Sec));
+    if (Relocations.empty())
+      continue;
+
+    W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
+                  << " {\n";
+    for (auto Reloc : Relocations) {
+      StringRef SymbolName = unwrapOrError(
+          Obj.getFileName(), Obj.getSymbolNameByIndex(Reloc.SymbolIndex));
+
+      DictScope RelocScope(W, "Relocation");
+      W.printHex("Virtual Address", Reloc.VirtualAddress);
+      W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
+      W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
+      W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
+      W.printNumber("Length", Reloc.getRelocatedLength());
+      W.printEnum("Type", (uint8_t)Reloc.Type,
+                  makeArrayRef(RelocationTypeNameclass));
+    }
+    W.unindent();
+    W.startLine() << "}\n";
+  }
 }
 
 static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {




More information about the llvm-commits mailing list