From c90c425735c2b803616c19dab30fcb73a1b5b9ed Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Sun, 31 May 2015 20:36:43 +0000 Subject: [PATCH] [Mips] Reading, merging and writing .MIPS.abiflags section http://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking llvm-svn: 238686 --- .../ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp | 607 ++++++++++++++++++--- lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h | 41 +- lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp | 32 +- lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h | 2 + lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp | 16 + lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h | 4 + .../ReaderWriter/ELF/Mips/MipsSectionChunks.cpp | 31 ++ lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h | 20 + lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp | 2 + lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h | 5 +- lld/test/elf/Mips/abi-flags-01.test | 35 ++ lld/test/elf/Mips/abi-flags-02.test | 92 ++++ lld/test/elf/Mips/abi-flags-03.test | 149 +++++ lld/test/elf/Mips/abi-flags-04.test | 125 +++++ lld/test/elf/Mips/abi-flags-05.test | 186 +++++++ lld/test/elf/Mips/abi-flags-06.test | 79 +++ lld/test/elf/Mips/abi-flags-07.test | 60 ++ lld/test/elf/Mips/abi-flags-08.test | 71 +++ 18 files changed, 1477 insertions(+), 80 deletions(-) create mode 100644 lld/test/elf/Mips/abi-flags-01.test create mode 100644 lld/test/elf/Mips/abi-flags-02.test create mode 100644 lld/test/elf/Mips/abi-flags-03.test create mode 100644 lld/test/elf/Mips/abi-flags-04.test create mode 100644 lld/test/elf/Mips/abi-flags-05.test create mode 100644 lld/test/elf/Mips/abi-flags-06.test create mode 100644 lld/test/elf/Mips/abi-flags-07.test create mode 100644 lld/test/elf/Mips/abi-flags-08.test diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp index df6fb05..922f670 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp @@ -12,41 +12,246 @@ #include "lld/ReaderWriter/ELFLinkingContext.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/MipsABIFlags.h" #include "llvm/Support/raw_ostream.h" +using namespace lld; +using namespace lld::elf; +using namespace llvm; using namespace llvm::ELF; +using namespace llvm::Mips; + +namespace { + +// The joined set of MIPS ISAs and MIPS ISA extensions. +enum MipsISAs { + ArchNone, + + // General ISAs + Arch1, + Arch2, + Arch3, + Arch4, + Arch5, + Arch32, + Arch32r2, + Arch32r3, + Arch32r5, + Arch32r6, + Arch64, + Arch64r2, + Arch64r3, + Arch64r5, + Arch64r6, + + // CPU specific ISAs + Arch3900, + Arch4010, + Arch4100, + Arch4111, + Arch4120, + Arch4650, + Arch5400, + Arch5500, + Arch5900, + Arch9000, + Arch10000, + ArchLs2e, + ArchLs2f, + ArchLs3a, + ArchOcteon, + ArchOcteonP, + ArchOcteon2, + ArchOcteon3, + ArchSB1, + ArchXLR +}; struct MipsISATreeEdge { - unsigned child; - unsigned parent; + MipsISAs child; + MipsISAs parent; +}; + +struct ElfArchPair { + uint32_t _elfFlag; + MipsISAs _arch; }; -static MipsISATreeEdge isaTree[] = { - // MIPS32R6 and MIPS64R6 are not compatible with other extensions - - // MIPS64 extensions. - {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64}, - // MIPS V extensions. - {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5}, - // MIPS IV extensions. - {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4}, - // MIPS III extensions. - {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3}, - // MIPS32 extensions. - {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32}, - // MIPS II extensions. - {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2}, - {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2}, - // MIPS I extensions. - {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1}, +struct AbiIsaArchPair { + uint8_t _isaLevel; + uint8_t _isaRev; + uint8_t _isaExt; + MipsISAs _arch; }; +} + +static const MipsISATreeEdge isaTree[] = { + // MIPS32R6 and MIPS64R6 are not compatible with other extensions + + // MIPS64R2 extensions. + {ArchOcteon3, ArchOcteon2}, + {ArchOcteon2, ArchOcteonP}, + {ArchOcteonP, ArchOcteon}, + {ArchOcteon, Arch64r2}, + {ArchLs3a, Arch64r2}, + + // MIPS64 extensions. + {Arch64r2, Arch64}, + {ArchSB1, Arch64}, + {ArchXLR, Arch64}, + + // MIPS V extensions. + {Arch64, Arch5}, + + // R5000 extensions. + {Arch5500, Arch5400}, + + // MIPS IV extensions. + {Arch5, Arch4}, + {Arch5400, Arch4}, + {Arch9000, Arch4}, -static bool matchMipsISA(unsigned base, unsigned ext) { + // VR4100 extensions. + {Arch4120, Arch4100}, + {Arch4111, Arch4100}, + + // MIPS III extensions. + {ArchLs2e, Arch3}, + {ArchLs2f, Arch3}, + {Arch4650, Arch3}, + {Arch4100, Arch3}, + {Arch4010, Arch3}, + {Arch5900, Arch3}, + {Arch4, Arch3}, + + // MIPS32 extensions. + {Arch32r2, Arch32}, + + // MIPS II extensions. + {Arch3, Arch2}, + {Arch32, Arch2}, + + // MIPS I extensions. + {Arch3900, Arch1}, + {Arch2, Arch1}, +}; + +// Conversion ELF arch flags => MipsISAs +static const ElfArchPair elfArchPairs[] = { + {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, Arch3900}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, Arch4010}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, Arch4100}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, Arch4111}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, Arch4120}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, Arch4650}, + {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, Arch5400}, + {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, Arch5500}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, Arch5900}, + {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, Arch9000}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, ArchLs2e}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, ArchLs2f}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, ArchLs3a}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteon}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3}, + {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchSB1}, + {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, ArchXLR}, + {EF_MIPS_ARCH_1, Arch1}, + {EF_MIPS_ARCH_2, Arch2}, + {EF_MIPS_ARCH_3, Arch3}, + {EF_MIPS_ARCH_4, Arch4}, + {EF_MIPS_ARCH_5, Arch5}, + {EF_MIPS_ARCH_32, Arch32}, + {EF_MIPS_ARCH_32R2, Arch32r2}, + {EF_MIPS_ARCH_32R6, Arch32r6}, + {EF_MIPS_ARCH_64, Arch64}, + {EF_MIPS_ARCH_64R2, Arch64r2}, + {EF_MIPS_ARCH_64R6, Arch64r6} +}; + +// Conversion MipsISAs => ELF arch flags +static const ElfArchPair archElfPairs[] = { + {EF_MIPS_ARCH_1, Arch1}, + {EF_MIPS_ARCH_2, Arch2}, + {EF_MIPS_ARCH_3, Arch3}, + {EF_MIPS_ARCH_4, Arch4}, + {EF_MIPS_ARCH_5, Arch5}, + {EF_MIPS_ARCH_32, Arch32}, + {EF_MIPS_ARCH_32R2, Arch32r2}, + {EF_MIPS_ARCH_32R2, Arch32r3}, + {EF_MIPS_ARCH_32R2, Arch32r5}, + {EF_MIPS_ARCH_32R6, Arch32r6}, + {EF_MIPS_ARCH_64, Arch64}, + {EF_MIPS_ARCH_64R2, Arch64r2}, + {EF_MIPS_ARCH_64R2, Arch64r3}, + {EF_MIPS_ARCH_64R2, Arch64r5}, + {EF_MIPS_ARCH_64R6, Arch64r6}, + {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, Arch3900}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, Arch4010}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, Arch4100}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, Arch4111}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, Arch4120}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, Arch4650}, + {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, Arch5400}, + {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, Arch5500}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, Arch5900}, + {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, Arch9000}, + {EF_MIPS_ARCH_4, Arch10000}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, ArchLs2e}, + {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, ArchLs2f}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, ArchLs3a}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteon}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteonP}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2}, + {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3}, + {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchSB1}, + {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchXLR} +}; + +// Conversion .MIPS.abiflags isa/level/extension <=> MipsISAs +static const AbiIsaArchPair abiIsaArchPair[] = { + { 0, 0, 0, ArchNone}, + { 1, 0, 0, Arch1}, + { 2, 0, 0, Arch2}, + { 3, 0, 0, Arch3}, + { 4, 0, 0, Arch4}, + { 5, 0, 0, Arch5}, + {32, 1, 0, Arch32}, + {32, 2, 0, Arch32r2}, + {32, 3, 0, Arch32r3}, + {32, 5, 0, Arch32r5}, + {32, 6, 0, Arch32r6}, + {64, 1, 0, Arch64}, + {64, 2, 0, Arch64r2}, + {64, 3, 0, Arch64r3}, + {64, 5, 0, Arch64r5}, + {64, 6, 0, Arch64r6}, + { 1, 0, AFL_EXT_3900, Arch3900}, + { 3, 0, AFL_EXT_4010, Arch4010}, + { 3, 0, AFL_EXT_4100, Arch4100}, + { 3, 0, AFL_EXT_4111, Arch4111}, + { 3, 0, AFL_EXT_4120, Arch4120}, + { 3, 0, AFL_EXT_4650, Arch4650}, + { 4, 0, AFL_EXT_5400, Arch5400}, + { 4, 0, AFL_EXT_5500, Arch5500}, + { 3, 0, AFL_EXT_5900, Arch5900}, + { 4, 0, AFL_EXT_10000, Arch10000}, + { 3, 0, AFL_EXT_LOONGSON_2E, ArchLs2e}, + { 3, 0, AFL_EXT_LOONGSON_2F, ArchLs2f}, + {64, 2, AFL_EXT_LOONGSON_3A, ArchLs3a}, + {64, 2, AFL_EXT_OCTEON, ArchOcteon}, + {64, 2, AFL_EXT_OCTEON2, ArchOcteon2}, + {64, 2, AFL_EXT_OCTEON3, ArchOcteon3}, + {64, 1, AFL_EXT_SB1, ArchSB1}, + {64, 1, AFL_EXT_XLR, ArchXLR} +}; + +static bool matchMipsISA(MipsISAs base, MipsISAs ext) { if (base == ext) return true; - if (base == EF_MIPS_ARCH_32 && matchMipsISA(EF_MIPS_ARCH_64, ext)) + if (base == Arch32 && matchMipsISA(Arch64, ext)) return true; - if (base == EF_MIPS_ARCH_32R2 && matchMipsISA(EF_MIPS_ARCH_64R2, ext)) + if (base == Arch32r2 && matchMipsISA(Arch64r2, ext)) return true; for (const auto &edge : isaTree) { if (ext == edge.child) { @@ -58,84 +263,272 @@ static bool matchMipsISA(unsigned base, unsigned ext) { return false; } +static bool is32BitElfFlags(unsigned flags) { + if (flags & EF_MIPS_32BITMODE) + return true; + + unsigned arch = flags & EF_MIPS_ARCH; + if (arch == EF_MIPS_ARCH_1 || arch == EF_MIPS_ARCH_2 || + arch == EF_MIPS_ARCH_32 || arch == EF_MIPS_ARCH_32R2 || + arch == EF_MIPS_ARCH_32R6) + return true; + + unsigned abi = flags & EF_MIPS_ABI; + if (abi == EF_MIPS_ABI_O32 || abi == EF_MIPS_ABI_EABI32) + return true; + + return false; +} + +static ErrorOr headerFlagsToIsa(uint32_t flags) { + uint32_t arch = flags & (EF_MIPS_ARCH | EF_MIPS_MACH); + for (const auto &p : elfArchPairs) + if (p._elfFlag == arch) + return p._arch; + return make_dynamic_error_code( + StringRef("Unknown EF_MIPS_ARCH | EF_MIPS_MACH flags (0x") + + Twine::utohexstr(arch) + ")"); +} + +static uint32_t isaToHeaderFlags(unsigned isa) { + for (const auto &p : archElfPairs) + if (p._arch == isa) + return p._elfFlag; + llvm_unreachable("Unknown MIPS ISA"); +} + +static ErrorOr flagsToAses(uint32_t flags) { + uint32_t ases = flags & EF_MIPS_ARCH_ASE; + switch (ases) { + case 0: + return 0; + case EF_MIPS_MICROMIPS: + return AFL_ASE_MICROMIPS; + case EF_MIPS_ARCH_ASE_M16: + return AFL_ASE_MIPS16; + case EF_MIPS_ARCH_ASE_MDMX: + return AFL_ASE_MDMX; + default: + return make_dynamic_error_code( + StringRef("Unknown EF_MIPS_ARCH_ASE flag (0x") + + Twine::utohexstr(ases) + ")"); + } +} + +static uint32_t asesToFlags(uint32_t ases) { + switch (ases) { + case AFL_ASE_MICROMIPS: + return EF_MIPS_MICROMIPS; + case AFL_ASE_MIPS16: + return EF_MIPS_ARCH_ASE_M16; + case AFL_ASE_MDMX: + return EF_MIPS_ARCH_ASE_MDMX; + default: + return 0; + } +} + +static ErrorOr sectionFlagsToIsa(uint8_t isaLevel, uint8_t isaRev, + uint8_t isaExt) { + for (const auto &p : abiIsaArchPair) + if (p._isaLevel == isaLevel && p._isaRev == isaRev && p._isaExt == isaExt) + return p._arch; + return make_dynamic_error_code( + StringRef("Unknown ISA level/revision/extension ") + Twine(isaLevel) + + "/" + Twine(isaRev) + "/" + Twine(isaExt)); +} + +static std::tuple isaToSectionFlags(unsigned isa) { + for (const auto &p : abiIsaArchPair) + if (p._arch == isa) + return std::make_tuple(p._isaLevel, p._isaRev, p._isaExt); + llvm_unreachable("Unknown MIPS ISA"); +} + +static bool checkCompatibility(const MipsAbiFlags &hdr, + const MipsAbiFlags &sec) { + uint32_t secIsa = ArchNone; + switch (sec._isa) { + case Arch32r3: + case Arch32r5: + secIsa = Arch32r2; + break; + case Arch64r3: + case Arch64r5: + secIsa = Arch64r2; + break; + default: + secIsa = sec._isa; + break; + } + if (secIsa != hdr._isa) { + llvm::errs() << "inconsistent ISA between .MIPS.abiflags " + "and ELF header e_flags field\n"; + return false; + } + if ((sec._ases & hdr._ases) != hdr._ases) { + llvm::errs() << "inconsistent ASEs between .MIPS.abiflags " + "and ELF header e_flags field\n"; + return false; + } + return true; +} + +static int compareFpAbi(uint32_t fpA, uint32_t fpB) { + if (fpA == fpB) + return 0; + if (fpB == Val_GNU_MIPS_ABI_FP_ANY) + return 1; + if (fpB == Val_GNU_MIPS_ABI_FP_64A && fpA == Val_GNU_MIPS_ABI_FP_64) + return 1; + if (fpB != Val_GNU_MIPS_ABI_FP_XX) + return -1; + if (fpA == Val_GNU_MIPS_ABI_FP_DOUBLE || fpA == Val_GNU_MIPS_ABI_FP_64 || + fpA == Val_GNU_MIPS_ABI_FP_64A) + return 1; + return -1; +} + +static StringRef getFpAbiName(uint32_t fpAbi) { + switch (fpAbi) { + case Val_GNU_MIPS_ABI_FP_ANY: + return ""; + case Val_GNU_MIPS_ABI_FP_DOUBLE: + return "-mdouble-float"; + case Val_GNU_MIPS_ABI_FP_SINGLE: + return "-msingle-float"; + case Val_GNU_MIPS_ABI_FP_SOFT: + return "-msoft-float"; + case Val_GNU_MIPS_ABI_FP_OLD_64: + return "-mips32r2 -mfp64 (old)"; + case Val_GNU_MIPS_ABI_FP_XX: + return "-mfpxx"; + case Val_GNU_MIPS_ABI_FP_64: + return "-mgp32 -mfp64"; + case Val_GNU_MIPS_ABI_FP_64A: + return "-mgp32 -mfp64 -mno-odd-spreg"; + default: + return ""; + } +} + +static uint32_t selectFpAbiFlag(uint32_t oldFp, uint32_t newFp) { + if (compareFpAbi(newFp, oldFp) >= 0) + return newFp; + if (compareFpAbi(oldFp, newFp) < 0) + llvm::errs() << "FP ABI " << getFpAbiName(oldFp) << " is incompatible with " + << getFpAbiName(newFp) << "\n"; + return oldFp; +} + namespace lld { namespace elf { +template uint32_t MipsAbiInfoHandler::getFlags() const { + std::lock_guard lock(_mutex); + uint32_t flags = 0; + if (_abiFlags.hasValue()) { + flags |= isaToHeaderFlags(_abiFlags->_isa); + flags |= asesToFlags(_abiFlags->_ases); + flags |= _abiFlags->_abi; + flags |= _abiFlags->_isPic ? EF_MIPS_PIC : 0; + flags |= _abiFlags->_isCPic ? EF_MIPS_CPIC : 0; + flags |= _abiFlags->_isNoReorder ? EF_MIPS_NOREORDER : 0; + flags |= _abiFlags->_is32BitMode ? EF_MIPS_32BITMODE : 0; + flags |= _abiFlags->_isNan2008 ? EF_MIPS_NAN2008 : 0; + } + return flags; +} + template -std::error_code MipsAbiInfoHandler::mergeFlags(uint32_t newFlags) { +llvm::Optional::Elf_Mips_RegInfo> +MipsAbiInfoHandler::getRegistersMask() const { + std::lock_guard lock(_mutex); + return _regMask; +} + +template +llvm::Optional::Elf_Mips_ABIFlags> +MipsAbiInfoHandler::getAbiFlags() const { + std::lock_guard lock(_mutex); + if (!_hasAbiSection) + return llvm::Optional(); + + Elf_Mips_ABIFlags sec; + sec.version = 0; + std::tie(sec.isa_level, sec.isa_rev, sec.isa_ext) = + isaToSectionFlags(_abiFlags->_isa); + sec.gpr_size = _abiFlags->_gprSize; + sec.cpr1_size = _abiFlags->_cpr1Size; + sec.cpr2_size = _abiFlags->_cpr2Size; + sec.fp_abi = _abiFlags->_fpAbi; + sec.ases = _abiFlags->_ases; + sec.flags1 = _abiFlags->_flags1; + sec.flags2 = 0; + return sec; +} + +template +std::error_code +MipsAbiInfoHandler::mergeFlags(uint32_t newFlags, + const Elf_Mips_ABIFlags *newSec) { + std::lock_guard lock(_mutex); + + ErrorOr abiFlags = createAbiFlags(newFlags, newSec); + if (auto ec = abiFlags.getError()) + return ec; + // We support two ABI: O32 and N64. The last one does not have // the corresponding ELF flag. - uint32_t inAbi = newFlags & EF_MIPS_ABI; uint32_t supportedAbi = ELFT::Is64Bits ? 0 : uint32_t(EF_MIPS_ABI_O32); - if (inAbi != supportedAbi) + if (abiFlags->_abi != supportedAbi) return make_dynamic_error_code("Unsupported ABI"); - // ... and reduced set of architectures ... - uint32_t newArch = newFlags & EF_MIPS_ARCH; - switch (newArch) { - case EF_MIPS_ARCH_1: - case EF_MIPS_ARCH_2: - case EF_MIPS_ARCH_3: - case EF_MIPS_ARCH_4: - case EF_MIPS_ARCH_5: - case EF_MIPS_ARCH_32: - case EF_MIPS_ARCH_64: - case EF_MIPS_ARCH_32R2: - case EF_MIPS_ARCH_64R2: - case EF_MIPS_ARCH_32R6: - case EF_MIPS_ARCH_64R6: - break; - default: - return make_dynamic_error_code("Unsupported instruction set"); - } - // ... and still do not support MIPS-16 extension. - if (newFlags & EF_MIPS_ARCH_ASE_M16) + if (abiFlags->_ases & AFL_ASE_MIPS16) return make_dynamic_error_code("Unsupported extension: MIPS16"); // PIC code is inherently CPIC and may not set CPIC flag explicitly. // Ensure that this flag will exist in the linked file. - if (newFlags & EF_MIPS_PIC) - newFlags |= EF_MIPS_CPIC; - - std::lock_guard lock(_mutex); + if (abiFlags->_isPic) + abiFlags->_isCPic = true; // If the old set of flags is empty, use the new one as a result. - if (!_flags) { - _flags = newFlags; + if (!_abiFlags.hasValue()) { + _abiFlags = *abiFlags; return std::error_code(); } // Check PIC / CPIC flags compatibility. - uint32_t newPic = newFlags & (EF_MIPS_PIC | EF_MIPS_CPIC); - uint32_t oldPic = _flags & (EF_MIPS_PIC | EF_MIPS_CPIC); - - if ((newPic != 0) != (oldPic != 0)) + if (abiFlags->_isCPic != _abiFlags->_isCPic) llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n"; - if (!(newPic & EF_MIPS_PIC)) - _flags &= ~EF_MIPS_PIC; - if (newPic) - _flags |= EF_MIPS_CPIC; + if (!abiFlags->_isPic) + _abiFlags->_isPic = false; + if (abiFlags->_isCPic) + _abiFlags->_isCPic = true; // Check mixing -mnan=2008 / -mnan=legacy modules. - if ((newFlags & EF_MIPS_NAN2008) != (_flags & EF_MIPS_NAN2008)) + if (abiFlags->_isNan2008 != _abiFlags->_isNan2008) return make_dynamic_error_code( "Linking -mnan=2008 and -mnan=legacy modules"); // Check ISA compatibility and update the extension flag. - uint32_t oldArch = _flags & EF_MIPS_ARCH; - if (!matchMipsISA(newArch, oldArch)) { - if (!matchMipsISA(oldArch, newArch)) + if (!matchMipsISA(MipsISAs(abiFlags->_isa), MipsISAs(_abiFlags->_isa))) { + if (!matchMipsISA(MipsISAs(_abiFlags->_isa), MipsISAs(abiFlags->_isa))) return make_dynamic_error_code("Linking modules with incompatible ISA"); - _flags &= ~EF_MIPS_ARCH; - _flags |= newArch; + _abiFlags->_isa = abiFlags->_isa; } - _flags |= newFlags & EF_MIPS_NOREORDER; - _flags |= newFlags & EF_MIPS_MICROMIPS; - _flags |= newFlags & EF_MIPS_NAN2008; - _flags |= newFlags & EF_MIPS_32BITMODE; + _abiFlags->_ases |= abiFlags->_ases; + _abiFlags->_isNoReorder = _abiFlags->_isNoReorder || abiFlags->_isNoReorder; + _abiFlags->_is32BitMode = _abiFlags->_is32BitMode || abiFlags->_is32BitMode; + + _abiFlags->_fpAbi = selectFpAbiFlag(_abiFlags->_fpAbi, abiFlags->_fpAbi); + _abiFlags->_gprSize = std::max(_abiFlags->_gprSize, abiFlags->_gprSize); + _abiFlags->_cpr1Size = std::max(_abiFlags->_cpr1Size, abiFlags->_cpr1Size); + _abiFlags->_cpr2Size = std::max(_abiFlags->_cpr2Size, abiFlags->_cpr2Size); + _abiFlags->_flags1 |= abiFlags->_flags1; return std::error_code(); } @@ -155,6 +548,80 @@ void MipsAbiInfoHandler::mergeRegistersMask( _regMask->ri_cprmask[3] = _regMask->ri_cprmask[3] | info.ri_cprmask[3]; } +template +ErrorOr +MipsAbiInfoHandler::createAbiFlags(uint32_t flags, + const Elf_Mips_ABIFlags *sec) { + ErrorOr hdrFlags = createAbiFromHeaderFlags(flags); + if (auto ec = hdrFlags.getError()) + return ec; + if (!sec) + return *hdrFlags; + ErrorOr secFlags = createAbiFromSection(*sec); + if (auto ec = secFlags.getError()) + return ec; + if (!checkCompatibility(*hdrFlags, *secFlags)) + return *hdrFlags; + + _hasAbiSection = true; + + secFlags->_abi = hdrFlags->_abi; + secFlags->_isPic = hdrFlags->_isPic; + secFlags->_isCPic = hdrFlags->_isCPic; + secFlags->_isNoReorder = hdrFlags->_isNoReorder; + secFlags->_is32BitMode = hdrFlags->_is32BitMode; + secFlags->_isNan2008 = hdrFlags->_isNan2008; + return *secFlags; +} + +template +ErrorOr +MipsAbiInfoHandler::createAbiFromHeaderFlags(uint32_t flags) { + MipsAbiFlags abi; + ErrorOr isa = headerFlagsToIsa(flags); + if (auto ec = isa.getError()) + return ec; + abi._isa = *isa; + + abi._fpAbi = Val_GNU_MIPS_ABI_FP_ANY; + abi._cpr1Size = AFL_REG_NONE; + abi._cpr2Size = AFL_REG_NONE; + abi._gprSize = is32BitElfFlags(flags) ? AFL_REG_32 : AFL_REG_64; + + ErrorOr ases = flagsToAses(flags); + if (auto ec = ases.getError()) + return ec; + abi._ases = *ases; + abi._flags1 = 0; + abi._abi = flags & EF_MIPS_ABI; + abi._isPic = flags & EF_MIPS_PIC; + abi._isCPic = flags & EF_MIPS_CPIC; + abi._isNoReorder = flags & EF_MIPS_NOREORDER; + abi._is32BitMode = flags & EF_MIPS_32BITMODE; + abi._isNan2008 = flags & EF_MIPS_NAN2008; + return abi; +} + +template +ErrorOr +MipsAbiInfoHandler::createAbiFromSection(const Elf_Mips_ABIFlags &sec) { + MipsAbiFlags abi; + ErrorOr isa = + sectionFlagsToIsa(sec.isa_level, sec.isa_rev, sec.isa_ext); + if (auto ec = isa.getError()) + return ec; + abi._isa = *isa; + abi._fpAbi = sec.fp_abi; + abi._cpr1Size = sec.cpr1_size; + abi._cpr2Size = sec.cpr2_size; + abi._gprSize = sec.gpr_size; + abi._ases = sec.ases; + abi._flags1 = sec.flags1; + if (sec.flags2 != 0) + return make_dynamic_error_code("unexpected non-zero 'flags2' value"); + return abi; +} + template class MipsAbiInfoHandler; template class MipsAbiInfoHandler; diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h b/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h index 8972089..eb0545c 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h @@ -11,33 +11,60 @@ #include "llvm/ADT/Optional.h" #include "llvm/Object/ELFTypes.h" +#include "llvm/Support/ErrorOr.h" #include #include namespace lld { namespace elf { +struct MipsAbiFlags { + unsigned _isa = 0; + unsigned _fpAbi = 0; + unsigned _ases = 0; + unsigned _flags1 = 0; + unsigned _gprSize = 0; + unsigned _cpr1Size = 0; + unsigned _cpr2Size = 0; + + unsigned _abi = 0; + + bool _isPic = false; + bool _isCPic = false; + bool _isNoReorder = false; + bool _is32BitMode = false; + bool _isNan2008 = false; +}; + template class MipsAbiInfoHandler { public: typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; + typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; MipsAbiInfoHandler() = default; - uint32_t getFlags() const { return _flags; } - const llvm::Optional &getRegistersMask() const { - return _regMask; - } + uint32_t getFlags() const; + llvm::Optional getRegistersMask() const; + llvm::Optional getAbiFlags() const; /// \brief Merge saved ELF header flags and the new set of flags. - std::error_code mergeFlags(uint32_t newFlags); + std::error_code mergeFlags(uint32_t newFlags, + const Elf_Mips_ABIFlags *newAbi); /// \brief Merge saved and new sets of registers usage masks. void mergeRegistersMask(const Elf_Mips_RegInfo &info); private: - std::mutex _mutex; - uint32_t _flags = 0; + mutable std::mutex _mutex; + bool _hasAbiSection = false; + llvm::Optional _abiFlags; llvm::Optional _regMask; + + llvm::ErrorOr createAbiFlags(uint32_t flags, + const Elf_Mips_ABIFlags *sec); + static llvm::ErrorOr createAbiFromHeaderFlags(uint32_t flags); + static llvm::ErrorOr + createAbiFromSection(const Elf_Mips_ABIFlags &sec); }; } // namespace elf diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp index 833c5ab6..1245e74 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp @@ -9,6 +9,7 @@ #include "MipsELFFile.h" #include "MipsTargetHandler.h" +#include "llvm/ADT/StringExtras.h" namespace lld { namespace elf { @@ -156,6 +157,31 @@ MipsELFFile::findRegInfoSec() const { return nullptr; } +template +ErrorOr::Elf_Mips_ABIFlags *> +MipsELFFile::findAbiFlagsSec() const { + const Elf_Shdr *sec = findSectionByType(SHT_MIPS_ABIFLAGS); + if (!sec) + return nullptr; + + auto contents = this->getSectionContents(sec); + if (std::error_code ec = contents.getError()) + return ec; + + ArrayRef raw = contents.get(); + if (raw.size() != sizeof(Elf_Mips_ABIFlags)) + return make_dynamic_error_code( + StringRef("Invalid size of MIPS_ABIFLAGS section")); + + const auto *abi = reinterpret_cast(raw.data()); + if (abi->version != 0) + return make_dynamic_error_code( + StringRef(".MIPS.abiflags section has unsupported version '") + + llvm::utostr(abi->version) + "'"); + + return abi; +} + template std::error_code MipsELFFile::readAuxData() { using namespace llvm::ELF; if (const Elf_Shdr *sec = findSectionByFlags(SHF_TLS)) { @@ -175,8 +201,12 @@ template std::error_code MipsELFFile::readAuxData() { _gp0 = regInfo->ri_gp_value; } + ErrorOr abiFlagsSec = findAbiFlagsSec(); + if (auto ec = abiFlagsSec.getError()) + return ec; + const Elf_Ehdr *hdr = this->_objFile->getHeader(); - if (std::error_code ec = abi.mergeFlags(hdr->e_flags)) + if (std::error_code ec = abi.mergeFlags(hdr->e_flags, abiFlagsSec.get())) return ec; return std::error_code(); diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h index b660858..69ba1cc 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFFile.h @@ -100,8 +100,10 @@ private: typedef typename llvm::object::ELFFile::Elf_Ehdr Elf_Ehdr; typedef llvm::object::Elf_Mips_RegInfo Elf_Mips_RegInfo; typedef llvm::object::Elf_Mips_Options Elf_Mips_Options; + typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; ErrorOr findRegInfoSec() const; + ErrorOr findAbiFlagsSec() const; std::error_code readAuxData(); diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp index 7afcf38..63d7d3c 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp @@ -85,6 +85,16 @@ MipsELFWriter::createOptionsSection(llvm::BumpPtrAllocator &alloc) { } template +unique_bump_ptr> +MipsELFWriter::createAbiFlagsSection(llvm::BumpPtrAllocator &alloc) { + typedef unique_bump_ptr> Ptr; + const auto &abi = _abiInfo.getAbiFlags(); + if (!abi.hasValue()) + return Ptr(); + return Ptr(new (alloc) MipsAbiFlagsSection(_ctx, _targetLayout, *abi)); +} + +template void MipsELFWriter::setAtomValue(StringRef name, uint64_t value) { AtomLayout *atom = _targetLayout.findAbsoluteAtom(name); assert(atom); @@ -117,6 +127,9 @@ void MipsDynamicLibraryWriter::createDefaultSections() { _reginfo = _writeHelper.createOptionsSection(this->_alloc); if (_reginfo) this->_layout.addSection(_reginfo.get()); + _abiFlags = _writeHelper.createAbiFlagsSection(this->_alloc); + if (_abiFlags) + this->_layout.addSection(_abiFlags.get()); } template @@ -235,6 +248,9 @@ template void MipsExecutableWriter::createDefaultSections() { _reginfo = _writeHelper.createOptionsSection(this->_alloc); if (_reginfo) this->_layout.addSection(_reginfo.get()); + _abiFlags = _writeHelper.createAbiFlagsSection(this->_alloc); + if (_abiFlags) + this->_layout.addSection(_abiFlags.get()); } template diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h index ddae9d4..31b84f9 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h @@ -31,6 +31,8 @@ public: std::unique_ptr> createRuntimeFile(); unique_bump_ptr> createOptionsSection(llvm::BumpPtrAllocator &alloc); + unique_bump_ptr> + createAbiFlagsSection(llvm::BumpPtrAllocator &alloc); private: MipsLinkingContext &_ctx; @@ -64,6 +66,7 @@ private: MipsELFWriter _writeHelper; MipsTargetLayout &_targetLayout; unique_bump_ptr> _reginfo; + unique_bump_ptr> _abiFlags; }; template @@ -90,6 +93,7 @@ private: MipsELFWriter _writeHelper; MipsTargetLayout &_targetLayout; unique_bump_ptr> _reginfo; + unique_bump_ptr> _abiFlags; }; } // elf diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp index 77440b0..d6318cb 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp @@ -89,6 +89,37 @@ template class MipsOptionsSection; template class MipsOptionsSection; template +MipsAbiFlagsSection::MipsAbiFlagsSection( + const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, + const Elf_Mips_ABIFlags &abiFlags) + : Section(ctx, ".MIPS.abiflags", "MipsAbiFlags"), _abiFlags(abiFlags), + _targetLayout(targetLayout) { + this->setOrder(MipsTargetLayout::ORDER_MIPS_ABI_FLAGS); + this->_alignment = 8; + this->_fsize = llvm::RoundUpToAlignment(sizeof(_abiFlags), this->_alignment); + this->_msize = this->_fsize; + this->_entSize = this->_fsize; + this->_type = SHT_MIPS_ABIFLAGS; + this->_flags = SHF_ALLOC; +} + +template +void MipsAbiFlagsSection::write(ELFWriter *writer, + TargetLayout &layout, + llvm::FileOutputBuffer &buffer) { + uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); + std::memcpy(dest, &_abiFlags, this->_fsize); +} + +template void MipsAbiFlagsSection::finalize() { + if (this->_outputSection) + this->_outputSection->setType(this->_type); +} + +template class MipsAbiFlagsSection; +template class MipsAbiFlagsSection; + +template MipsGOTSection::MipsGOTSection(const MipsLinkingContext &ctx) : AtomSection(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_, MipsTargetLayout::ORDER_GOT), diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h index b60abef..e545f65 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h @@ -60,6 +60,26 @@ private: MipsTargetLayout &_targetLayout; }; +/// \brief Handle .MIPS.abiflags section +template class MipsAbiFlagsSection : public Section { +public: + typedef llvm::object::Elf_Mips_ABIFlags Elf_Mips_ABIFlags; + + MipsAbiFlagsSection(const ELFLinkingContext &ctx, + MipsTargetLayout &targetLayout, + const Elf_Mips_ABIFlags &abiFlags); + + bool hasOutputSegment() const override { return true; } + + void write(ELFWriter *writer, TargetLayout &layout, + llvm::FileOutputBuffer &buffer) override; + void finalize() override; + +private: + Elf_Mips_ABIFlags _abiFlags; + MipsTargetLayout &_targetLayout; +}; + /// \brief Handle Mips GOT section template class MipsGOTSection : public AtomSection { public: diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp index ed03052..c80f156 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp @@ -38,6 +38,8 @@ MipsTargetLayout::getSegmentType(Section *section) const { return llvm::ELF::PT_MIPS_REGINFO; case ORDER_MIPS_OPTIONS: return llvm::ELF::PT_LOAD; + case ORDER_MIPS_ABI_FLAGS: + return llvm::ELF::PT_MIPS_ABIFLAGS; default: return TargetLayout::getSegmentType(section); } diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h index 868ba96..09431cb 100644 --- a/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h +++ b/lld/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h @@ -21,8 +21,9 @@ class MipsLinkingContext; template class MipsTargetLayout final : public TargetLayout { public: enum MipsSectionOrder { - ORDER_MIPS_REGINFO = TargetLayout::ORDER_RO_NOTE + 1, - ORDER_MIPS_OPTIONS + ORDER_MIPS_ABI_FLAGS = TargetLayout::ORDER_RO_NOTE + 1, + ORDER_MIPS_REGINFO, + ORDER_MIPS_OPTIONS, }; MipsTargetLayout(MipsLinkingContext &ctx); diff --git a/lld/test/elf/Mips/abi-flags-01.test b/lld/test/elf/Mips/abi-flags-01.test new file mode 100644 index 0000000..74d13e6 --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-01.test @@ -0,0 +1,35 @@ +# Check rejecting .MIPS.abiflags section with a wrong version. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so %t.o 2>&1 \ +# RUN: | FileCheck %s + +# CHECK: {{.*}}abi-flags-01.test.tmp.o: .MIPS.abiflags section has unsupported version '1' + +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + Version: 1 + ISA: MIPS32 + +Symbols: + Global: + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 diff --git a/lld/test/elf/Mips/abi-flags-02.test b/lld/test/elf/Mips/abi-flags-02.test new file mode 100644 index 0000000..6436ddd --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-02.test @@ -0,0 +1,92 @@ +# Check generation of .MIPS.abiflags section under the following conditions: +# - There is the only input object file +# - The input file has valid .MIPS.abiflags section +# +# The .MIPS.abiflags section in the output file should have the same +# settings as the input section. + +# RUN: yaml2obj -format=elf %s > %t.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t.o +# RUN: llvm-readobj -s -program-headers -mips-abi-flags %t.so | FileCheck %s + +# CHECK: Section { +# CHECK: Index: 1 +# CHECK-NEXT: Name: .MIPS.abiflags +# CHECK-NEXT: Type: SHT_MIPS_ABIFLAGS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x{{[0-9A-F]+}} +# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}} +# CHECK-NEXT: Size: 24 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 8 +# CHECK-NEXT: EntrySize: 24 +# CHECK-NEXT: } + +# CHECK: ProgramHeaders [ +# CHECK: ProgramHeader { +# CHECK: Type: PT_MIPS_ABIFLAGS (0x70000003) +# CHECK-NEXT: Offset: 0x{{[0-9A-F]+}} +# CHECK-NEXT: VirtualAddress: 0x{{[0-9A-F]+}} +# CHECK-NEXT: PhysicalAddress: 0x{{[0-9A-F]+}} +# CHECK-NEXT: FileSize: 24 +# CHECK-NEXT: MemSize: 24 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 8 +# CHECK-NEXT: } + +# CHECK: MIPS ABI Flags { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: ISA: MIPS32r2 +# CHECK-NEXT: ISA Extension: None (0x0) +# CHECK-NEXT: ASEs [ (0x800) +# CHECK-NEXT: microMIPS (0x800) +# CHECK-NEXT: ] +# CHECK-NEXT: FP ABI: Hard float (32-bit CPU, Any FPU) (0x5) +# CHECK-NEXT: GPR size: 32 +# CHECK-NEXT: CPR1 size: 32 +# CHECK-NEXT: CPR2 size: 0 +# CHECK-NEXT: Flags 1 [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Flags 2: 0x0 +# CHECK-NEXT: } + +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + ISAExtension: EXT_NONE + ASEs: [ MICROMIPS ] + FpABI: FP_XX + GPRSize: REG_32 + CPR1Size: REG_32 + CPR2Size: REG_NONE + Flags1: [ ] + Flags2: 0x0 + +Symbols: + Global: + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 diff --git a/lld/test/elf/Mips/abi-flags-03.test b/lld/test/elf/Mips/abi-flags-03.test new file mode 100644 index 0000000..2150d36 --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-03.test @@ -0,0 +1,149 @@ +# Check generation of .MIPS.abiflags section under the following conditions: +# - There are multiple input object files +# - Every input file has valid .MIPS.abiflags section +# - All .MIPS.abiflags sections are compatible with each other +# +# The .MIPS.abiflags section in the output file should reproduce result +# of merging input object file sections. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t3.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o %t2.o %t3.o +# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s + +# CHECK: MIPS ABI Flags { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: ISA: MIPS32r2 +# CHECK-NEXT: ISA Extension: None (0x0) +# CHECK-NEXT: ASEs [ (0x810) +# CHECK-NEXT: MDMX (0x10) +# CHECK-NEXT: microMIPS (0x800) +# CHECK-NEXT: ] +# CHECK-NEXT: FP ABI: Hard float (double precision) (0x1) +# CHECK-NEXT: GPR size: 32 +# CHECK-NEXT: CPR1 size: 64 +# CHECK-NEXT: CPR2 size: 0 +# CHECK-NEXT: Flags 1 [ (0x1) +# CHECK-NEXT: ODDSPREG +# CHECK-NEXT: ] +# CHECK-NEXT: Flags 2: 0x0 +# CHECK-NEXT: } + +# o1.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + ISAExtension: EXT_NONE + ASEs: [ MDMX ] + FpABI: FP_DOUBLE + GPRSize: REG_32 + CPR1Size: REG_64 + CPR2Size: REG_NONE + Flags1: [ ] + Flags2: 0x0 + +Symbols: + Global: + - Name: T1 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 + +# o2.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + ISAExtension: EXT_NONE + ASEs: [ MICROMIPS ] + FpABI: FP_XX + GPRSize: REG_32 + CPR1Size: REG_32 + CPR2Size: REG_NONE + Flags1: [ODDSPREG] + Flags2: 0x0 + +Symbols: + Global: + - Name: T2 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 + +# o3.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + ISAExtension: EXT_NONE + ASEs: [ MICROMIPS ] + FpABI: FP_XX + GPRSize: REG_32 + CPR1Size: REG_32 + CPR2Size: REG_NONE + Flags1: [ ] + Flags2: 0x0 + +Symbols: + Global: + - Name: T3 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 +... diff --git a/lld/test/elf/Mips/abi-flags-04.test b/lld/test/elf/Mips/abi-flags-04.test new file mode 100644 index 0000000..f344fae --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-04.test @@ -0,0 +1,125 @@ +# Check generation of .MIPS.abiflags section under the following conditions: +# - There are multiple input object files +# - Every input file has valid .MIPS.abiflags section +# - .MIPS.abiflags sections have different but compatible FP ABI +# +# The .MIPS.abiflags section in the output file should reproduce result +# of merging FP ABI flags. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-xx.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-double.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-64.o +# RUN: yaml2obj -format=elf -docnum 4 %s > %t-64a.o + +# RUN: lld -flavor gnu -target mipsel -shared -o %t1 %t-xx.o %t-double.o +# RUN: llvm-readobj -mips-abi-flags %t1 | FileCheck -check-prefix=XX-DOUBLE %s + +# XX-DOUBLE: FP ABI: Hard float (double precision) (0x1) +# XX-DOUBLE: GPR size: 32 +# XX-DOUBLE: CPR1 size: 32 +# XX-DOUBLE: Flags 1 [ (0x0) + +# RUN: lld -flavor gnu -target mipsel -shared -o %t2 %t-xx.o %t-64.o +# RUN: llvm-readobj -mips-abi-flags %t2 | FileCheck -check-prefix=XX-64 %s + +# XX-64: FP ABI: Hard float (32-bit CPU, 64-bit FPU) (0x6) +# XX-64: GPR size: 32 +# XX-64: CPR1 size: 64 +# XX-64: Flags 1 [ (0x1) +# XX-64: ODDSPREG (0x1) + +# RUN: lld -flavor gnu -target mipsel -shared -o %t3 %t-xx.o %t-64a.o +# RUN: llvm-readobj -mips-abi-flags %t3 | FileCheck -check-prefix=XX-64A %s + +# XX-64A: FP ABI: Hard float compat (32-bit CPU, 64-bit FPU) (0x7) +# XX-64A: GPR size: 32 +# XX-64A: CPR1 size: 64 +# XX-64A: Flags 1 [ (0x0) + +# RUN: lld -flavor gnu -target mipsel -shared -o %t4 %t-64.o %t-64a.o +# RUN: llvm-readobj -mips-abi-flags %t4 | FileCheck -check-prefix=64-64A %s + +# 64-64A: FP ABI: Hard float (32-bit CPU, 64-bit FPU) (0x6) +# 64-64A: GPR size: 32 +# 64-64A: CPR1 size: 64 +# 64-64A: Flags 1 [ (0x1) +# 64-64A: ODDSPREG (0x1) + +# xx.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + FpABI: FP_XX + GPRSize: REG_32 + CPR1Size: REG_32 + +# double.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + FpABI: FP_DOUBLE + GPRSize: REG_32 + CPR1Size: REG_32 + +# 64.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + FpABI: FP_64 + GPRSize: REG_32 + CPR1Size: REG_64 + Flags1: [ODDSPREG] + +# 64a.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + FpABI: FP_64A + GPRSize: REG_32 + CPR1Size: REG_64 + Flags1: [] +... diff --git a/lld/test/elf/Mips/abi-flags-05.test b/lld/test/elf/Mips/abi-flags-05.test new file mode 100644 index 0000000..515cbcf --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-05.test @@ -0,0 +1,186 @@ +# Check generation of .MIPS.abiflags section under the following conditions: +# - There are multiple input object files +# - Every input file has valid .MIPS.abiflags section +# - .MIPS.abiflags sections have different and incompatible FP ABI +# +# The .MIPS.abiflags section in the output file should reproduce result +# of merging FP ABI flags but the linker must show a warning. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-xx.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-dbl.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-sgl.o +# RUN: yaml2obj -format=elf -docnum 4 %s > %t-soft.o +# RUN: yaml2obj -format=elf -docnum 5 %s > %t-64.o +# RUN: yaml2obj -format=elf -docnum 6 %s > %t-64a.o + +# RUN: lld -flavor gnu -target mipsel -shared -o %t1 %t-xx.o %t-sgl.o 2>&1 \ +# RUN: | FileCheck -check-prefix=XX-SINGLE-WARN %s + +# XX-SINGLE-WARN: FP ABI {{-mfpxx|-msingle-float}} is incompatible with {{-msingle-float|-mfpxx}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t2 %t-xx.o %t-soft.o 2>&1 \ +# RUN: | FileCheck -check-prefix=XX-SOFT-WARN %s + +# XX-SOFT-WARN: FP ABI {{-mfpxx|-msoft-float}} is incompatible with {{-msoft-float|-mfpxx}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t3 %t-dbl.o %t-sgl.o 2>&1 \ +# RUN: | FileCheck -check-prefix=DOUBLE-SINGLE-WARN %s + +# DOUBLE-SINGLE-WARN: FP ABI {{-mdouble-float|-msingle-float}} is incompatible with {{-msingle-float|-mdouble-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t4 %t-dbl.o %t-soft.o 2>&1 \ +# RUN: | FileCheck -check-prefix=DOUBLE-SOFT-WARN %s + +# DOUBLE-SOFT-WARN: FP ABI {{-mdouble-float|-msoft-float}} is incompatible with {{-msoft-float|-mdouble-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t5 %t-dbl.o %t-64.o 2>&1 \ +# RUN: | FileCheck -check-prefix=DOUBLE-64-WARN %s + +# DOUBLE-64-WARN: FP ABI {{-mdouble-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-mdouble-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t6 %t-dbl.o %t-64a.o 2>&1 \ +# RUN: | FileCheck -check-prefix=DOUBLE-64A-WARN %s + +# DOUBLE-64A-WARN: FP ABI {{-mdouble-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-mdouble-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t7 %t-sgl.o %t-soft.o 2>&1 \ +# RUN: | FileCheck -check-prefix=SINGLE-SOFT-WARN %s + +# SINGLE-SOFT-WARN: FP ABI {{-msingle-float|-msoft-float}} is incompatible with {{-msoft-float|-msingle-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t8 %t-sgl.o %t-64.o 2>&1 \ +# RUN: | FileCheck -check-prefix=SINGLE-64-WARN %s + +# SINGLE-64-WARN: FP ABI {{-msingle-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-msingle-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t9 %t-sgl.o %t-64a.o 2>&1 \ +# RUN: | FileCheck -check-prefix=SINGLE-64A-WARN %s + +# SINGLE-64A-WARN: FP ABI {{-msingle-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-msingle-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t10 %t-soft.o %t-64.o 2>&1 \ +# RUN: | FileCheck -check-prefix=SOFT-64-WARN %s + +# SOFT-64-WARN: FP ABI {{-msoft-float|-mgp32 -mfp64}} is incompatible with {{-mgp32 -mfp64|-msoft-float}} + +# RUN: lld -flavor gnu -target mipsel -shared -o %t11 %t-soft.o %t-64a.o 2>&1 \ +# RUN: | FileCheck -check-prefix=SOFT-64A-WARN %s + +# SOFT-64A-WARN: FP ABI {{-msoft-float|-mgp32 -mfp64 -mno-odd-spreg}} is incompatible with {{-mgp32 -mfp64 -mno-odd-spreg|-msoft-float}} + +# xx.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + FpABI: FP_XX + GPRSize: REG_32 + CPR1Size: REG_32 + +# double.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + FpABI: FP_DOUBLE + GPRSize: REG_32 + CPR1Size: REG_32 + +# single.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + FpABI: FP_SINGLE + GPRSize: REG_32 + CPR1Size: REG_32 + +# soft.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + FpABI: FP_SOFT + GPRSize: REG_32 + CPR1Size: REG_NONE + +# 64.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + FpABI: FP_64 + GPRSize: REG_32 + CPR1Size: REG_64 + Flags1: [ODDSPREG] + +# 64a.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_PIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + FpABI: FP_64A + GPRSize: REG_32 + CPR1Size: REG_64 + Flags1: [] +... diff --git a/lld/test/elf/Mips/abi-flags-06.test b/lld/test/elf/Mips/abi-flags-06.test new file mode 100644 index 0000000..4837c96 --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-06.test @@ -0,0 +1,79 @@ +# Check generation of .MIPS.abiflags section under the following conditions: +# - There are multiple input object files +# - Not all input files have a .MIPS.abiflags section +# +# The .MIPS.abiflags section in the output file should reproduce result +# of merging input object file sections and data come from ELF header flags. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-abi.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-elf.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t-abi.o %t-elf.o +# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s + +# CHECK: MIPS ABI Flags { +# CHECK-NEXT: Version: 0 +# CHECK-NEXT: ISA: MIPS32r2 +# CHECK-NEXT: ISA Extension: None (0x0) +# CHECK-NEXT: ASEs [ (0x810) +# CHECK-NEXT: MDMX (0x10) +# CHECK-NEXT: microMIPS (0x800) +# CHECK-NEXT: ] +# CHECK-NEXT: FP ABI: Hard float (double precision) (0x1) +# CHECK-NEXT: GPR size: 32 +# CHECK-NEXT: CPR1 size: 64 +# CHECK-NEXT: CPR2 size: 0 +# CHECK-NEXT: Flags 1 [ (0x0) +# CHECK-NEXT: ] +# CHECK-NEXT: Flags 2: 0x0 +# CHECK-NEXT: } + +# abi.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 1 + ISAExtension: EXT_NONE + ASEs: [ MDMX ] + FpABI: FP_DOUBLE + GPRSize: REG_32 + CPR1Size: REG_64 + CPR2Size: REG_NONE + Flags1: [ ] + Flags2: 0x0 + +# elf.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +Symbols: + Global: + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 +... diff --git a/lld/test/elf/Mips/abi-flags-07.test b/lld/test/elf/Mips/abi-flags-07.test new file mode 100644 index 0000000..3f14128b --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-07.test @@ -0,0 +1,60 @@ +# Check that .MIPS.abiflags section is not written if no input object files +# contain that section. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t1.o %t2.o +# RUN: llvm-readobj -mips-abi-flags %t.so | FileCheck %s + +# CHECK: There is no .MIPS.abiflags section in the file. + +# abi.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32, EF_MIPS_ARCH_ASE_MDMX] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +Symbols: + Global: + - Name: T0 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 + +# elf.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, + EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS] + +Sections: +- Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 4 + AddressAlign: 16 + +Symbols: + Global: + - Name: T1 + Section: .text + Type: STT_FUNC + Value: 0 + Size: 4 +... diff --git a/lld/test/elf/Mips/abi-flags-08.test b/lld/test/elf/Mips/abi-flags-08.test new file mode 100644 index 0000000..d14e40a --- /dev/null +++ b/lld/test/elf/Mips/abi-flags-08.test @@ -0,0 +1,71 @@ +# Check that the linker shows errors if ELF header flags +# and .MIPS.abiflags section are incompatible. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t-isa.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t-ext.o +# RUN: yaml2obj -format=elf -docnum 3 %s > %t-ases.o +# RUN: lld -flavor gnu -target mipsel -shared -o %t1.so %t-isa.o 2>&1 \ +# RUN: | FileCheck -check-prefix=ISA-ERR %s +# RUN: lld -flavor gnu -target mipsel -shared -o %t2.so %t-ext.o 2>&1 \ +# RUN: | FileCheck -check-prefix=EXT-ERR %s +# RUN: lld -flavor gnu -target mipsel -shared -o %t3.so %t-ases.o 2>&1 \ +# RUN: | FileCheck -check-prefix=ASE-ERR %s +# RUN: llvm-readobj -mips-abi-flags %t1.so %t2.so %t3.so \ +# RUN: | FileCheck -check-prefix=SEC %s + +# ISA-ERR: inconsistent ISA between .MIPS.abiflags and ELF header e_flags field +# EXT-ERR: inconsistent ISA between .MIPS.abiflags and ELF header e_flags field +# ASE-ERR: inconsistent ASEs between .MIPS.abiflags and ELF header e_flags field + +# SEC: There is no .MIPS.abiflags section in the file. + +# isa.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + +# ext.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_3, EF_MIPS_MACH_4650] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS3 + ISAExtension: EXT_4120 + +# ases.o +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS] + +Sections: +- Name: .MIPS.abiflags + Type: SHT_MIPS_ABIFLAGS + AddressAlign: 8 + ISA: MIPS32 + ISARevision: 2 + ASEs: [] + +... -- 2.7.4