Skip to content

Commit

Permalink
[XCOFF] Decode the relocation entries of loader section of xcoff for …
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
diggerlin committed Dec 14, 2022
1 parent 07335f9 commit a274d62
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 70 deletions.
4 changes: 4 additions & 0 deletions llvm/docs/CommandGuide/llvm-readobj.rst
Expand Up @@ -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
-----------

Expand Down
12 changes: 12 additions & 0 deletions llvm/include/llvm/BinaryFormat/XCOFF.h
Expand Up @@ -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
Expand Down
99 changes: 55 additions & 44 deletions llvm/include/llvm/Object/XCOFFObjectFile.h
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
@@ -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
102 changes: 102 additions & 0 deletions 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: }

0 comments on commit a274d62

Please sign in to comment.