[Mips] Support writing .MIPS.options section into the linked file

In case of MIPS N64 ABI linker should merge registers usage masks stored
in the input .MIPS.options sections and save result into the output
.MIPS.options section.

llvm-svn: 234115
This commit is contained in:
Simon Atanasyan 2015-04-05 09:01:46 +00:00
parent b2d1c0c09c
commit 4c5b23f6df
9 changed files with 443 additions and 20 deletions

View File

@ -75,14 +75,17 @@ void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
template <class ELFT>
void MipsDynamicLibraryWriter<ELFT>::createDefaultSections() {
DynamicLibraryWriter<ELFT>::createDefaultSections();
const auto &mask =
static_cast<const MipsLinkingContext &>(this->_ctx).getMergeReginfoMask();
if (!ELFT::Is64Bits && mask.hasValue()) {
const auto &ctx = static_cast<const MipsLinkingContext &>(this->_ctx);
const auto &mask = ctx.getMergeReginfoMask();
if (!mask.hasValue())
return;
if (ELFT::Is64Bits)
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc)
MipsReginfoSection<ELFT>(this->_ctx, _targetLayout, *mask));
this->_layout.addSection(_reginfo.get());
}
new (this->_alloc) MipsOptionsSection<ELFT>(ctx, _targetLayout, *mask));
else
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc) MipsReginfoSection<ELFT>(ctx, _targetLayout, *mask));
this->_layout.addSection(_reginfo.get());
}
template <class ELFT>

View File

@ -126,14 +126,17 @@ void MipsExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
template <class ELFT> void MipsExecutableWriter<ELFT>::createDefaultSections() {
ExecutableWriter<ELFT>::createDefaultSections();
const auto &mask =
static_cast<const MipsLinkingContext &>(this->_ctx).getMergeReginfoMask();
if (!ELFT::Is64Bits && mask.hasValue()) {
const auto &ctx = static_cast<const MipsLinkingContext &>(this->_ctx);
const auto &mask = ctx.getMergeReginfoMask();
if (!mask.hasValue())
return;
if (ELFT::Is64Bits)
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc)
MipsReginfoSection<ELFT>(this->_ctx, _targetLayout, *mask));
this->_layout.addSection(_reginfo.get());
}
new (this->_alloc) MipsOptionsSection<ELFT>(ctx, _targetLayout, *mask));
else
_reginfo = unique_bump_ptr<Section<ELFT>>(
new (this->_alloc) MipsReginfoSection<ELFT>(ctx, _targetLayout, *mask));
this->_layout.addSection(_reginfo.get());
}
template <class ELFT>

View File

@ -33,7 +33,7 @@ public:
this->_type = SHT_MIPS_REGINFO;
this->_flags = SHF_ALLOC;
memset(&_reginfo, 0, sizeof(_reginfo));
std::memset(&_reginfo, 0, sizeof(_reginfo));
_reginfo.ri_gprmask = reginfo._gpRegMask;
_reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
_reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
@ -62,6 +62,63 @@ private:
MipsTargetLayout<ELFT> &_targetLayout;
};
/// \brief Handle .MIPS.options section
template <class ELFT> class MipsOptionsSection : public Section<ELFT> {
public:
typedef typename std::vector<MipsReginfo>::const_iterator mask_const_iterator;
MipsOptionsSection(const ELFLinkingContext &ctx,
MipsTargetLayout<ELFT> &targetLayout,
const MipsReginfo &reginfo)
: Section<ELFT>(ctx, ".MIPS.options", "MipsOptions"),
_targetLayout(targetLayout) {
this->setOrder(MipsTargetLayout<ELFT>::ORDER_RO_NOTE);
this->_entSize = 1;
this->_alignment = 8;
this->_fsize = llvm::RoundUpToAlignment(
sizeof(Elf_Mips_Options) + sizeof(Elf_RegInfo), this->_alignment);
this->_msize = this->_fsize;
this->_type = SHT_MIPS_OPTIONS;
this->_flags = SHF_ALLOC | SHF_MIPS_NOSTRIP;
_header.kind = ODK_REGINFO;
_header.size = this->_fsize;
_header.section = 0;
_header.info = 0;
std::memset(&_reginfo, 0, sizeof(_reginfo));
_reginfo.ri_gprmask = reginfo._gpRegMask;
_reginfo.ri_cprmask[0] = reginfo._cpRegMask[0];
_reginfo.ri_cprmask[1] = reginfo._cpRegMask[1];
_reginfo.ri_cprmask[2] = reginfo._cpRegMask[2];
_reginfo.ri_cprmask[3] = reginfo._cpRegMask[3];
}
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
llvm::FileOutputBuffer &buffer) override {
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
std::memset(dest, 0, this->_fsize);
std::memcpy(dest, &_header, sizeof(_header));
std::memcpy(dest + sizeof(_header), &_reginfo, sizeof(_reginfo));
}
void finalize() override {
const AtomLayout *gpAtom = _targetLayout.getGP();
_reginfo.ri_gp_value = gpAtom ? gpAtom->_virtualAddr : 0;;
if (this->_outputSection)
this->_outputSection->setType(this->_type);
}
private:
typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
Elf_Mips_Options _header;
Elf_RegInfo _reginfo;
MipsTargetLayout<ELFT> &_targetLayout;
};
/// \brief Handle Mips GOT section
template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
public:

View File

@ -0,0 +1,30 @@
# Check that LLD does not write a .MIPS.options section if input
# object file does not contain such section.
# RUN: yaml2obj -format=elf %s > %t.o
# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t.o
# RUN: llvm-readobj -s %t.so | FileCheck %s
# CHECK-NOT: Name: .MIPS.options
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Symbols:
Global:
- Name: T0
Section: .text
Type: STT_FUNC
Value: 0
Size: 4

View File

@ -0,0 +1,93 @@
# Check merging input .MIPS.options sections.
# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t1.o %t2.o
# RUN: llvm-readobj -s %t.so | FileCheck -check-prefix=SEC %s
# RUN: llvm-objdump -s -t %t.so | FileCheck -check-prefix=RAW %s
# SEC: Index: 1
# SEC-NEXT: Name: .MIPS.options (1)
# SEC-NEXT: Type: SHT_MIPS_OPTIONS (0x7000000D)
# SEC-NEXT: Flags [ (0x8000002)
# SEC-NEXT: SHF_ALLOC (0x2)
# SEC-NEXT: SHF_MIPS_NOSTRIP (0x8000000)
# SEC-NEXT: ]
# SEC-NEXT: Address: {{[0-9A-F]+}}
# SEC-NEXT: Offset: {{[0-9A-F]+}}
# SEC-NEXT: Size: 40
# SEC-NEXT: Link: 0
# SEC-NEXT: Info: 0
# SEC-NEXT: AddressAlignment: 8
# SEC-NEXT: EntrySize: 1
# RAW: Contents of section .MIPS.options:
# RAW-NEXT: 1000 01280000 00000000 f0000001 00000000
# RAW-NEXT: 1010 e0000002 d0000003 b0000004 c0000005
# RAW-NEXT: 1020 f09f0000 00000000
# RAW: SYMBOL TABLE:
# RAW: 0000000000009ff0 g *ABS* 00000000 _gp
# t1.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
# v ODK_NULL 0x18 bytes long v ODK_REGINFO
Content: "0018000000000000000000000000000000000000000000000128000000000000F000000000000000E0000000D0000000B0000000C00000000010000000000000"
Symbols:
Global:
- Name: T0
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
# t2.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
# v ODK_NULL 0x18 bytes long v ODK_REGINFO
Content: "00180000000000000000000000000000000000000000000001280000000000000000000100000000000000020000000300000004000000050000010000000000"
Symbols:
Global:
- Name: T1
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
...

View File

@ -0,0 +1,41 @@
# Check handling a zero-filled input .MIPS.options section.
# RUN: yaml2obj -format=elf %s > %t.o
# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t.o
# RUN: llvm-objdump -s -t %t.so | FileCheck %s
# CHECK: Contents of section .MIPS.options:
# CHECK-NEXT: 1000 01280000 00000000 00000000 00000000
# CHECK-NEXT: 1010 00000000 00000000 00000000 00000000
# CHECK-NEXT: 1020 f09f0000 00000000
# CHECK: SYMBOL TABLE:
# CHECK: 00009ff0 g *ABS* 00000000 _gp
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
Content: "01280000000000000000000000000000000000000000000000000000000000000000000000000000"
Symbols:
Global:
- Name: T0
Section: .text
Type: STT_FUNC
Value: 0
Size: 4

View File

@ -0,0 +1,77 @@
# Check that .MIPS.options sections from shared libraries do not affect
# output .MIPS.options section content.
# RUN: yaml2obj -format=elf -docnum 1 %s > %t.so.o
# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t.so.o
# RUN: yaml2obj -format=elf -docnum 2 %s > %t.exe.o
# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t.so %t.exe.o
# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
# CHECK: Contents of section .MIPS.options:
# CHECK-NEXT: 120001000 01280000 00000000 44444444 00000000
# CHECK-NEXT: 120001010 44444444 44444444 44444444 44444444
# CHECK-NEXT: 120001020 f09f0020 01000000
# CHECK: SYMBOL TABLE:
# CHECK: 20009ff0 g *ABS* 00000000 _gp
# t.so.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
Content: "01280000000000001111111100000000111111111111111111111111111111110010000000000000"
Symbols:
Global:
- Name: T1
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
# t.exe.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
Content: "01280000000000004444444400000000444444444444444444444444444444440010000000000000"
Symbols:
Global:
- Name: T0
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
...

View File

@ -0,0 +1,119 @@
# Check that .MIPS.options section gets register usage mask from "used" files
# only. In this test case we take only t2.o from liboptions.a and should not
# add register usage masks from t1.o to the output .MIPS.options section.
# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
# RUN: llvm-ar q %T/liboptions.a %t1.o %t2.o
# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o
# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t3.o -L%T -loptions
# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
# CHECK: Contents of section .MIPS.options:
# CHECK-NEXT: 120001000 01280000 00000000 66666666 00000000
# CHECK-NEXT: 120001010 66666666 66666666 66666666 66666666
# CHECK-NEXT: 120001020 f09f0020 01000000
# CHECK: SYMBOL TABLE:
# CHECK: 20009ff0 g *ABS* 00000000 _gp
# t1.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
Content: "01280000000000001111111100000000111111111111111111111111111111110010000000000000"
Symbols:
Global:
- Name: T1
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
# t2.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
Content: "01280000000000002222222200000000222222222222222222222222222222220010000000000000"
Symbols:
Global:
- Name: T2
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
# t3.o
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_REL
Machine: EM_MIPS
Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ARCH_64R2]
Sections:
- Name: .text
Type: SHT_PROGBITS
Size: 4
AddressAlign: 16
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Name: .rel.text
Type: SHT_REL
Info: .text
AddressAlign: 4
Relocations:
- Offset: 0
Symbol: T2
Type: R_MIPS_32
- Name: .MIPS.options
Type: SHT_MIPS_OPTIONS
Flags: [ SHF_ALLOC ]
AddressAlign: 8
Content: "01280000000000004444444400000000444444444444444444444444444444440010000000000000"
Symbols:
Global:
- Name: T0
Section: .text
Type: STT_FUNC
Value: 0
Size: 4
- Name: T2
...

View File

@ -6,24 +6,24 @@
# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
# SYM: Name: L1 (1)
# SYM-NEXT: Value: 0x134
# SYM-NEXT: Value: 0x1A4
# SYM-NEXT: Size: 4
# SYM-NEXT: Binding: Local (0x0)
# SYM-NEXT: Type: Function (0x2)
# SYM-NEXT: Other: 0
# SYM-NEXT: Section: .text (0x4)
# SYM-NEXT: Section: .text (0x5)
# SYM: Name: _gp (34)
# SYM-NEXT: Value: 0x8FF0
# SYM-NEXT: Value: 0x9FF0
# SYM-NEXT: Size: 0
# SYM-NEXT: Binding: Global (0x1)
# SYM-NEXT: Type: Object (0x1)
# SYM-NEXT: Other: 0
# SYM-NEXT: Section: Absolute (0xFFF1)
# 0xffff8144 == 0x0 (addend) + 0x0134 (L1) + 0x1000 (GP0) - 0x8ff0 (_gp)
# 0xffff71b4 == 0x0 (addend) + 0x01A4 (L1) + 0x1000 (GP0) - 0x9ff0 (_gp)
# SEC: Contents of section .rodata:
# SEC-NEXT: 013c 4481ffff 00000000 00000000 00000000
# SEC-NEXT: 01ac b471ffff 00000000 00000000 00000000
!ELF
FileHeader: