[lld] r246334 - [Mips] Initial support of the MIPS N32 ABI
Simon Atanasyan via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 28 14:39:00 PDT 2015
Author: atanasyan
Date: Fri Aug 28 16:39:00 2015
New Revision: 246334
URL: http://llvm.org/viewvc/llvm-project?rev=246334&view=rev
Log:
[Mips] Initial support of the MIPS N32 ABI
Added:
lld/trunk/test/elf/Mips/e-flags-merge-12.test
lld/trunk/test/elf/Mips/exe-fileheader-n32.test
lld/trunk/test/elf/Mips/interpreter-n32.test
Modified:
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp Fri Aug 28 16:39:00 2015
@@ -489,6 +489,21 @@ MipsAbiInfoHandler<ELFT>::getAbiFlags()
return sec;
}
+template <class ELFT> MipsAbi MipsAbiInfoHandler<ELFT>::getAbi() const {
+ if (!_abiFlags.hasValue())
+ return ELFT::Is64Bits ? MipsAbi::N64 : MipsAbi::O32;
+ switch (_abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)) {
+ case EF_MIPS_ABI_O32:
+ return MipsAbi::O32;
+ case EF_MIPS_ABI2:
+ return MipsAbi::N32;
+ case 0:
+ return MipsAbi::N64;
+ default:
+ llvm_unreachable("Unknown ABI flag");
+ }
+}
+
template <class ELFT>
std::error_code
MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags,
@@ -499,11 +514,15 @@ MipsAbiInfoHandler<ELFT>::mergeFlags(uin
if (auto ec = abiFlags.getError())
return ec;
- // We support two ABI: O32 and N64. The last one does not have
+ // We support three ABI: O32, N32, and N64. The last one does not have
// the corresponding ELF flag.
- uint32_t supportedAbi = ELFT::Is64Bits ? 0 : uint32_t(EF_MIPS_ABI_O32);
- if (abiFlags->_abi != supportedAbi)
- return make_dynamic_error_code("Unsupported ABI");
+ if (ELFT::Is64Bits) {
+ if (abiFlags->_abi)
+ return make_dynamic_error_code("Unsupported ABI");
+ } else {
+ if (!(abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)))
+ return make_dynamic_error_code("Unsupported ABI");
+ }
// ... and still do not support MIPS-16 extension.
if (abiFlags->_ases & AFL_ASE_MIPS16)
@@ -520,6 +539,10 @@ MipsAbiInfoHandler<ELFT>::mergeFlags(uin
return std::error_code();
}
+ // Check ABI compatibility.
+ if (abiFlags->_abi != _abiFlags->_abi)
+ return make_dynamic_error_code("Linking modules with incompatible ABI");
+
// Check PIC / CPIC flags compatibility.
if (abiFlags->_isCPic != _abiFlags->_isCPic)
llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
@@ -614,7 +637,7 @@ MipsAbiInfoHandler<ELFT>::createAbiFromH
return ec;
abi._ases = *ases;
abi._flags1 = 0;
- abi._abi = flags & EF_MIPS_ABI;
+ abi._abi = flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
abi._isPic = flags & EF_MIPS_PIC;
abi._isCPic = flags & EF_MIPS_CPIC;
abi._isNoReorder = flags & EF_MIPS_NOREORDER;
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h Fri Aug 28 16:39:00 2015
@@ -18,6 +18,8 @@
namespace lld {
namespace elf {
+enum class MipsAbi { O32, N32, N64 };
+
struct MipsAbiFlags {
unsigned _isa = 0;
unsigned _fpAbi = 0;
@@ -53,6 +55,8 @@ public:
llvm::Optional<Elf_Mips_RegInfo> getRegistersMask() const;
llvm::Optional<Elf_Mips_ABIFlags> getAbiFlags() const;
+ MipsAbi getAbi() const;
+
/// \brief Merge saved ELF header flags and the new set of flags.
std::error_code mergeFlags(uint32_t newFlags,
const Elf_Mips_ABIFlags *newAbi);
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp Fri Aug 28 16:39:00 2015
@@ -46,9 +46,16 @@ MipsLinkingContext::MipsLinkingContext(l
: ELFLinkingContext(triple, createTarget(triple, *this)) {}
uint64_t MipsLinkingContext::getBaseAddress() const {
- if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
- return getTriple().isArch64Bit() ? 0x120000000 : 0x400000;
- return _baseAddress;
+ if (_baseAddress != 0 || getOutputELFType() != llvm::ELF::ET_EXEC)
+ return _baseAddress;
+ switch (getAbi()) {
+ case MipsAbi::O32:
+ return 0x0400000;
+ case MipsAbi::N32:
+ return 0x10000000;
+ case MipsAbi::N64:
+ return 0x120000000;
+ }
}
StringRef MipsLinkingContext::entrySymbolName() const {
@@ -58,7 +65,14 @@ StringRef MipsLinkingContext::entrySymbo
}
StringRef MipsLinkingContext::getDefaultInterpreter() const {
- return getTriple().isArch64Bit() ? "/lib64/ld.so.1" : "/lib/ld.so.1";
+ switch (getAbi()) {
+ case MipsAbi::O32:
+ return "/lib/ld.so.1";
+ case MipsAbi::N32:
+ return "/lib32/ld.so.1";
+ case MipsAbi::N64:
+ return "/lib64/ld.so.1";
+ }
}
void MipsLinkingContext::addPasses(PassManager &pm) {
@@ -124,6 +138,11 @@ bool MipsLinkingContext::isRelativeReloc
}
}
+MipsAbi MipsLinkingContext::getAbi() const {
+ auto &handler = static_cast<MipsBaseTargetHandler &>(getTargetHandler());
+ return handler.getAbi();
+}
+
const Registry::KindStrings kindStrings[] = {
#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
#include "llvm/Support/ELFRelocs/Mips.def"
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h Fri Aug 28 16:39:00 2015
@@ -9,6 +9,7 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
+#include "MipsAbiInfoHandler.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
@@ -45,6 +46,8 @@ public:
bool isCopyRelocation(const Reference &r) const override;
bool isPLTRelocation(const Reference &r) const override;
bool isRelativeReloc(const Reference &r) const override;
+
+ MipsAbi getAbi() const;
};
} // elf
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp Fri Aug 28 16:39:00 2015
@@ -61,6 +61,30 @@ static const uint8_t mipsLePlt0AtomConte
0xfe, 0xff, 0x18, 0x27 // subu $24, $24, 2
};
+// N32 big-endian PLT0 entry
+static const uint8_t mipsN32BePlt0AtomContent[] = {
+ 0x3c, 0x0e, 0x00, 0x00, // lui $14, %hi(&GOTPLT[0])
+ 0x8d, 0xd9, 0x00, 0x00, // lw $25, %lo(&GOTPLT[0])($14)
+ 0x25, 0xce, 0x00, 0x00, // addiu $14, $14, %lo(&GOTPLT[0])
+ 0x03, 0x0e, 0xc0, 0x23, // subu $24, $24, $14
+ 0x03, 0xe0, 0x78, 0x25, // move $15, $31
+ 0x00, 0x18, 0xc0, 0x82, // srl $24, $24, 2
+ 0x03, 0x20, 0xf8, 0x09, // jalr $25
+ 0x27, 0x18, 0xff, 0xfe // subu $24, $24, 2
+};
+
+// N32 little-endian PLT0 entry
+static const uint8_t mipsN32LePlt0AtomContent[] = {
+ 0x00, 0x00, 0x0e, 0x3c, // lui $14, %hi(&GOTPLT[0])
+ 0x00, 0x00, 0xd9, 0x8d, // lw $25, %lo(&GOTPLT[0])($14)
+ 0x00, 0x00, 0xce, 0x25, // addiu $14, $14, %lo(&GOTPLT[0])
+ 0x23, 0xc0, 0x0e, 0x03, // subu $24, $24, $14
+ 0x25, 0x78, 0xe0, 0x03, // move $15, $31
+ 0x82, 0xc0, 0x18, 0x00, // srl $24, $24, 2
+ 0x09, 0xf8, 0x20, 0x03, // jalr $25
+ 0xfe, 0xff, 0x18, 0x27 // subu $24, $24, 2
+};
+
// microMIPS big-endian PLT0 entry
static const uint8_t microMipsBePlt0AtomContent[] = {
0x79, 0x80, 0x00, 0x00, // addiupc $3, (&GOTPLT[0]) - .
@@ -285,6 +309,27 @@ template <> ArrayRef<uint8_t> PLT0Atom<E
return llvm::makeArrayRef(mipsLePlt0AtomContent);
}
+template <class ELFT> class PLT0N32Atom : public PLTAtom {
+public:
+ PLT0N32Atom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
+ // Setup reference to fixup the PLT0 entry.
+ addReferenceELF_Mips(R_MIPS_HI16, 0, got, 0);
+ addReferenceELF_Mips(R_MIPS_LO16, 4, got, 0);
+ addReferenceELF_Mips(R_MIPS_LO16, 8, got, 0);
+ }
+
+ ArrayRef<uint8_t> rawContent() const override {
+ llvm_unreachable("PLT0 is not applicable for this target");
+ }
+};
+
+template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32BE>::rawContent() const {
+ return llvm::makeArrayRef(mipsN32BePlt0AtomContent);
+}
+template <> ArrayRef<uint8_t> PLT0N32Atom<ELF32LE>::rawContent() const {
+ return llvm::makeArrayRef(mipsN32LePlt0AtomContent);
+}
+
template <class ELFT> class PLT0MicroAtom : public PLTAtom {
public:
PLT0MicroAtom(const Atom *got, const File &f) : PLTAtom(f, ".plt") {
@@ -1253,6 +1298,8 @@ PLTAtom *RelocationPass<ELFT>::createPLT
if (isMicroMips)
return new (_file._alloc) PLT0MicroAtom<ELFT>(ga0, _file);
+ if (_ctx.getAbi() == MipsAbi::N32)
+ return new (_file._alloc) PLT0N32Atom<ELFT>(ga0, _file);
return new (_file._alloc) PLT0Atom<ELFT>(ga0, _file);
}
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp Fri Aug 28 16:39:00 2015
@@ -53,6 +53,10 @@ std::unique_ptr<Writer> MipsTargetHandle
}
}
+template <class ELFT> MipsAbi MipsTargetHandler<ELFT>::getAbi() const {
+ return _abiInfoHandler.getAbi();
+}
+
template class MipsTargetHandler<ELF32BE>;
template class MipsTargetHandler<ELF32LE>;
template class MipsTargetHandler<ELF64BE>;
Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h?rev=246334&r1=246333&r2=246334&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h Fri Aug 28 16:39:00 2015
@@ -17,8 +17,14 @@
namespace lld {
namespace elf {
+class MipsBaseTargetHandler : public TargetHandler {
+public:
+ virtual MipsAbi getAbi() const = 0;
+};
+
/// \brief TargetHandler for Mips
-template <class ELFT> class MipsTargetHandler final : public TargetHandler {
+template <class ELFT>
+class MipsTargetHandler final : public MipsBaseTargetHandler {
public:
MipsTargetHandler(MipsLinkingContext &ctx);
@@ -28,6 +34,7 @@ public:
std::unique_ptr<Reader> getDSOReader() override;
const TargetRelocationHandler &getRelocationHandler() const override;
std::unique_ptr<Writer> getWriter() override;
+ MipsAbi getAbi() const override;
private:
MipsLinkingContext &_ctx;
Added: lld/trunk/test/elf/Mips/e-flags-merge-12.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/e-flags-merge-12.test?rev=246334&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/e-flags-merge-12.test (added)
+++ lld/trunk/test/elf/Mips/e-flags-merge-12.test Fri Aug 28 16:39:00 2015
@@ -0,0 +1,44 @@
+# Check that LLD shows an error and does not link files with O32 and N32 ABIs.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t-o32.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t-n32.o
+
+# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so \
+# RUN: %t-o32.o %t-n32.o 2>&1 | FileCheck %s
+
+# CHECK: Linking modules with incompatible ABI
+
+# o32.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32,
+ EF_MIPS_32BITMODE, EF_MIPS_ARCH_64]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+
+# n32.o
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI2,
+ EF_MIPS_ARCH_64]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x04
+...
Added: lld/trunk/test/elf/Mips/exe-fileheader-n32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/exe-fileheader-n32.test?rev=246334&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/exe-fileheader-n32.test (added)
+++ lld/trunk/test/elf/Mips/exe-fileheader-n32.test Fri Aug 28 16:39:00 2015
@@ -0,0 +1,65 @@
+# Check ELF Header for N32 ABI executable file.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -o %t.exe %t.o
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: Format: ELF32-mips
+# CHECK-NEXT: Arch: mipsel
+# CHECK-NEXT: AddressSize: 32bit
+# CHECK-NEXT: LoadName:
+# CHECK-NEXT: ElfHeader {
+# CHECK-NEXT: Ident {
+# CHECK-NEXT: Magic: (7F 45 4C 46)
+# CHECK-NEXT: Class: 32-bit
+# CHECK-NEXT: DataEncoding: LittleEndian
+# CHECK-NEXT: FileVersion: 1
+# CHECK-NEXT: OS/ABI: SystemV
+# CHECK-NEXT: ABIVersion: 0
+# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT: }
+# CHECK-NEXT: Type: Executable
+# CHECK-NEXT: Machine: EM_MIPS
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: 0x10000130
+# CHECK-NEXT: ProgramHeaderOffset: 0x34
+# CHECK-NEXT: SectionHeaderOffset: 0x22C0
+# CHECK-NEXT: Flags [ (0x60000027)
+# CHECK-NEXT: EF_MIPS_ABI2
+# CHECK-NEXT: EF_MIPS_ARCH_64
+# CHECK-NEXT: EF_MIPS_CPIC
+# CHECK-NEXT: EF_MIPS_NOREORDER
+# CHECK-NEXT: EF_MIPS_PIC
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 52
+# CHECK-NEXT: ProgramHeaderEntrySize: 32
+# CHECK-NEXT: ProgramHeaderCount: {{[0-9]+}}
+# CHECK-NEXT: SectionHeaderEntrySize: 40
+# CHECK-NEXT: SectionHeaderCount: {{[0-9]+}}
+# CHECK-NEXT: StringTableSectionIndex: {{[0-9]+}}
+# CHECK-NEXT: }
+
+---
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+ EF_MIPS_ABI2, EF_MIPS_ARCH_64 ]
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 16
+ Size: 8
+
+Symbols:
+ Local:
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ Global:
+ - Name: __start
+ Section: .text
+...
Added: lld/trunk/test/elf/Mips/interpreter-n32.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/interpreter-n32.test?rev=246334&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/interpreter-n32.test (added)
+++ lld/trunk/test/elf/Mips/interpreter-n32.test Fri Aug 28 16:39:00 2015
@@ -0,0 +1,27 @@
+# Check program interpreter setup in case of N32 ABI.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: lld -flavor gnu -target mipsel -o %t.exe %t.o
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .interp:
+# CHECK-NEXT: {{[0-9a-f ]+}} /lib32/ld.so.1.
+
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [ EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ARCH_64, EF_MIPS_ABI2 ]
+
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 16
+ Size: 8
+
+Symbols:
+ Global:
+ - Name: __start
+ Section: .text
More information about the llvm-commits
mailing list