diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -342,6 +342,10 @@ 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 --- a/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -46,6 +46,18 @@ 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 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -195,36 +195,8 @@ 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 @@ 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 struct ExceptionSectionEntry { union { support::ubig32_t SymbolIdx; @@ -468,20 +493,6 @@ }; template 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 --- /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 --- /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 --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -155,10 +155,12 @@ 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 @@ 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 --- a/llvm/tools/llvm-readobj/Opts.td +++ b/llvm/tools/llvm-readobj/Opts.td @@ -91,6 +91,7 @@ def exception_section : FF<"exception-section" , "Display the exception section entries">, Group; def loader_section_header : FF<"loader-section-header" , "Display the loader section header">, Group; def loader_section_symbols : FF<"loader-section-symbols" , "Display the loader section symbol table">, Group; +def loader_section_relocations : FF<"loader-section-relocations" , "Display the loader section relocation entries">, Group; 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 --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -40,7 +40,8 @@ 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 @@ void printLoaderSectionSymbols(uintptr_t LoaderSectAddr); template void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr); + template + void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr, + StringRef SymbolName); + void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr); + template + void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr); + const XCOFFObjectFile &Obj; + const static int32_t FirstSymIdxOfLoaderSec = 3; }; } // anonymous namespace @@ -138,7 +148,8 @@ 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 LoaderSectionAddrOrError = Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER); @@ -155,13 +166,12 @@ 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 @@ LoaderSectionHeader32>(LoaderSectionAddr); } +const EnumEntry 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 +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(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(Type)) + << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8) + << " " << SymbolName << " (" + << LoaderSecRelEntPtr->SymbolIndex << ")\n"; + } +} + +template +void XCOFFDumper::printLoaderSectionRelocationEntriesHelper( + uintptr_t LoaderSectionAddr) { + const LoaderSectionHeader *LoaderSec = + reinterpret_cast(LoaderSectionAddr); + const LoaderSectionRelocationEntry *LoaderSecRelEntPtr = + reinterpret_cast( + 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( + LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) + + SymOffset); + + Expected 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( + LoaderSectionAddr); + else + printLoaderSectionRelocationEntriesHelper( + LoaderSectionAddr); +} + template void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const { if (ExceptionSectEnt.getReason()) @@ -309,18 +453,6 @@ printRelocations(Obj.sections32()); } -const EnumEntry 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 void XCOFFDumper::printRelocation(RelTy Reloc) { Expected ErrOrSymbolName = Obj.getSymbolNameByIndex(Reloc.SymbolIndex); diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -164,6 +164,7 @@ static bool XCOFFAuxiliaryHeader; static bool XCOFFLoaderSectionHeader; static bool XCOFFLoaderSectionSymbol; +static bool XCOFFLoaderSectionRelocation; static bool XCOFFExceptionSection; OutputStyleTy Output = OutputStyleTy::LLVM; @@ -307,6 +308,8 @@ 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 @@ } 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();