[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