[Mips] Reading, merging and writing .MIPS.abiflags section
http://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking llvm-svn: 238686
This commit is contained in:
parent
3eec407a53
commit
c90c425735
|
@ -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;
|
||||
};
|
||||
|
||||
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 ElfArchPair {
|
||||
uint32_t _elfFlag;
|
||||
MipsISAs _arch;
|
||||
};
|
||||
|
||||
static bool matchMipsISA(unsigned base, unsigned ext) {
|
||||
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},
|
||||
|
||||
// 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<MipsISAs> 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<uint32_t> 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<MipsISAs> 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<uint8_t, uint8_t, uint32_t> 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 "<any>";
|
||||
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 "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
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 <class ELFT> uint32_t MipsAbiInfoHandler<ELFT>::getFlags() const {
|
||||
std::lock_guard<std::mutex> 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 <class ELFT>
|
||||
std::error_code MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags) {
|
||||
llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_RegInfo>
|
||||
MipsAbiInfoHandler<ELFT>::getRegistersMask() const {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
return _regMask;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_ABIFlags>
|
||||
MipsAbiInfoHandler<ELFT>::getAbiFlags() const {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
if (!_hasAbiSection)
|
||||
return llvm::Optional<Elf_Mips_ABIFlags>();
|
||||
|
||||
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 <class ELFT>
|
||||
std::error_code
|
||||
MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags,
|
||||
const Elf_Mips_ABIFlags *newSec) {
|
||||
std::lock_guard<std::mutex> lock(_mutex);
|
||||
|
||||
ErrorOr<MipsAbiFlags> 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<std::mutex> 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<ELFT>::mergeRegistersMask(
|
|||
_regMask->ri_cprmask[3] = _regMask->ri_cprmask[3] | info.ri_cprmask[3];
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ErrorOr<MipsAbiFlags>
|
||||
MipsAbiInfoHandler<ELFT>::createAbiFlags(uint32_t flags,
|
||||
const Elf_Mips_ABIFlags *sec) {
|
||||
ErrorOr<MipsAbiFlags> hdrFlags = createAbiFromHeaderFlags(flags);
|
||||
if (auto ec = hdrFlags.getError())
|
||||
return ec;
|
||||
if (!sec)
|
||||
return *hdrFlags;
|
||||
ErrorOr<MipsAbiFlags> 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 <class ELFT>
|
||||
ErrorOr<MipsAbiFlags>
|
||||
MipsAbiInfoHandler<ELFT>::createAbiFromHeaderFlags(uint32_t flags) {
|
||||
MipsAbiFlags abi;
|
||||
ErrorOr<MipsISAs> 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<uint32_t> 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 <class ELFT>
|
||||
ErrorOr<MipsAbiFlags>
|
||||
MipsAbiInfoHandler<ELFT>::createAbiFromSection(const Elf_Mips_ABIFlags &sec) {
|
||||
MipsAbiFlags abi;
|
||||
ErrorOr<MipsISAs> 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<ELF32LE>;
|
||||
template class MipsAbiInfoHandler<ELF64LE>;
|
||||
|
||||
|
|
|
@ -11,33 +11,60 @@
|
|||
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/Object/ELFTypes.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include <mutex>
|
||||
#include <system_error>
|
||||
|
||||
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 ELFT> class MipsAbiInfoHandler {
|
||||
public:
|
||||
typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
|
||||
typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
|
||||
|
||||
MipsAbiInfoHandler() = default;
|
||||
|
||||
uint32_t getFlags() const { return _flags; }
|
||||
const llvm::Optional<Elf_Mips_RegInfo> &getRegistersMask() const {
|
||||
return _regMask;
|
||||
}
|
||||
uint32_t getFlags() const;
|
||||
llvm::Optional<Elf_Mips_RegInfo> getRegistersMask() const;
|
||||
llvm::Optional<Elf_Mips_ABIFlags> 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<MipsAbiFlags> _abiFlags;
|
||||
llvm::Optional<Elf_Mips_RegInfo> _regMask;
|
||||
|
||||
llvm::ErrorOr<MipsAbiFlags> createAbiFlags(uint32_t flags,
|
||||
const Elf_Mips_ABIFlags *sec);
|
||||
static llvm::ErrorOr<MipsAbiFlags> createAbiFromHeaderFlags(uint32_t flags);
|
||||
static llvm::ErrorOr<MipsAbiFlags>
|
||||
createAbiFromSection(const Elf_Mips_ABIFlags &sec);
|
||||
};
|
||||
|
||||
} // namespace elf
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "MipsELFFile.h"
|
||||
#include "MipsTargetHandler.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
|
@ -156,6 +157,31 @@ MipsELFFile<ELFT>::findRegInfoSec() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
ErrorOr<const typename MipsELFFile<ELFT>::Elf_Mips_ABIFlags *>
|
||||
MipsELFFile<ELFT>::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<uint8_t> 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<const Elf_Mips_ABIFlags *>(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 <class ELFT> std::error_code MipsELFFile<ELFT>::readAuxData() {
|
||||
using namespace llvm::ELF;
|
||||
if (const Elf_Shdr *sec = findSectionByFlags(SHF_TLS)) {
|
||||
|
@ -175,8 +201,12 @@ template <class ELFT> std::error_code MipsELFFile<ELFT>::readAuxData() {
|
|||
_gp0 = regInfo->ri_gp_value;
|
||||
}
|
||||
|
||||
ErrorOr<const Elf_Mips_ABIFlags *> 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();
|
||||
|
|
|
@ -100,8 +100,10 @@ private:
|
|||
typedef typename llvm::object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
|
||||
typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
|
||||
typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
|
||||
typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
|
||||
|
||||
ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const;
|
||||
ErrorOr<const Elf_Mips_ABIFlags*> findAbiFlagsSec() const;
|
||||
|
||||
std::error_code readAuxData();
|
||||
|
||||
|
|
|
@ -84,6 +84,16 @@ MipsELFWriter<ELFT>::createOptionsSection(llvm::BumpPtrAllocator &alloc) {
|
|||
MipsReginfoSection<ELFT>(_ctx, _targetLayout, *regMask));
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
unique_bump_ptr<Section<ELFT>>
|
||||
MipsELFWriter<ELFT>::createAbiFlagsSection(llvm::BumpPtrAllocator &alloc) {
|
||||
typedef unique_bump_ptr<Section<ELFT>> Ptr;
|
||||
const auto &abi = _abiInfo.getAbiFlags();
|
||||
if (!abi.hasValue())
|
||||
return Ptr();
|
||||
return Ptr(new (alloc) MipsAbiFlagsSection<ELFT>(_ctx, _targetLayout, *abi));
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void MipsELFWriter<ELFT>::setAtomValue(StringRef name, uint64_t value) {
|
||||
AtomLayout *atom = _targetLayout.findAbsoluteAtom(name);
|
||||
|
@ -117,6 +127,9 @@ void MipsDynamicLibraryWriter<ELFT>::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 <class ELFT>
|
||||
|
@ -235,6 +248,9 @@ template <class ELFT> void MipsExecutableWriter<ELFT>::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 <class ELFT>
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
|
||||
unique_bump_ptr<Section<ELFT>>
|
||||
createOptionsSection(llvm::BumpPtrAllocator &alloc);
|
||||
unique_bump_ptr<Section<ELFT>>
|
||||
createAbiFlagsSection(llvm::BumpPtrAllocator &alloc);
|
||||
|
||||
private:
|
||||
MipsLinkingContext &_ctx;
|
||||
|
@ -64,6 +66,7 @@ private:
|
|||
MipsELFWriter<ELFT> _writeHelper;
|
||||
MipsTargetLayout<ELFT> &_targetLayout;
|
||||
unique_bump_ptr<Section<ELFT>> _reginfo;
|
||||
unique_bump_ptr<Section<ELFT>> _abiFlags;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -90,6 +93,7 @@ private:
|
|||
MipsELFWriter<ELFT> _writeHelper;
|
||||
MipsTargetLayout<ELFT> &_targetLayout;
|
||||
unique_bump_ptr<Section<ELFT>> _reginfo;
|
||||
unique_bump_ptr<Section<ELFT>> _abiFlags;
|
||||
};
|
||||
|
||||
} // elf
|
||||
|
|
|
@ -88,6 +88,37 @@ template <class ELFT> void MipsOptionsSection<ELFT>::finalize() {
|
|||
template class MipsOptionsSection<ELF32LE>;
|
||||
template class MipsOptionsSection<ELF64LE>;
|
||||
|
||||
template <class ELFT>
|
||||
MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(
|
||||
const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout,
|
||||
const Elf_Mips_ABIFlags &abiFlags)
|
||||
: Section<ELFT>(ctx, ".MIPS.abiflags", "MipsAbiFlags"), _abiFlags(abiFlags),
|
||||
_targetLayout(targetLayout) {
|
||||
this->setOrder(MipsTargetLayout<ELFT>::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 <class ELFT>
|
||||
void MipsAbiFlagsSection<ELFT>::write(ELFWriter *writer,
|
||||
TargetLayout<ELFT> &layout,
|
||||
llvm::FileOutputBuffer &buffer) {
|
||||
uint8_t *dest = buffer.getBufferStart() + this->fileOffset();
|
||||
std::memcpy(dest, &_abiFlags, this->_fsize);
|
||||
}
|
||||
|
||||
template <class ELFT> void MipsAbiFlagsSection<ELFT>::finalize() {
|
||||
if (this->_outputSection)
|
||||
this->_outputSection->setType(this->_type);
|
||||
}
|
||||
|
||||
template class MipsAbiFlagsSection<ELF32LE>;
|
||||
template class MipsAbiFlagsSection<ELF64LE>;
|
||||
|
||||
template <class ELFT>
|
||||
MipsGOTSection<ELFT>::MipsGOTSection(const MipsLinkingContext &ctx)
|
||||
: AtomSection<ELFT>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_,
|
||||
|
|
|
@ -60,6 +60,26 @@ private:
|
|||
MipsTargetLayout<ELFT> &_targetLayout;
|
||||
};
|
||||
|
||||
/// \brief Handle .MIPS.abiflags section
|
||||
template <class ELFT> class MipsAbiFlagsSection : public Section<ELFT> {
|
||||
public:
|
||||
typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;
|
||||
|
||||
MipsAbiFlagsSection(const ELFLinkingContext &ctx,
|
||||
MipsTargetLayout<ELFT> &targetLayout,
|
||||
const Elf_Mips_ABIFlags &abiFlags);
|
||||
|
||||
bool hasOutputSegment() const override { return true; }
|
||||
|
||||
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
|
||||
llvm::FileOutputBuffer &buffer) override;
|
||||
void finalize() override;
|
||||
|
||||
private:
|
||||
Elf_Mips_ABIFlags _abiFlags;
|
||||
MipsTargetLayout<ELFT> &_targetLayout;
|
||||
};
|
||||
|
||||
/// \brief Handle Mips GOT section
|
||||
template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
|
||||
public:
|
||||
|
|
|
@ -38,6 +38,8 @@ MipsTargetLayout<ELFT>::getSegmentType(Section<ELFT> *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<ELFT>::getSegmentType(section);
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ class MipsLinkingContext;
|
|||
template <class ELFT> class MipsTargetLayout final : public TargetLayout<ELFT> {
|
||||
public:
|
||||
enum MipsSectionOrder {
|
||||
ORDER_MIPS_REGINFO = TargetLayout<ELFT>::ORDER_RO_NOTE + 1,
|
||||
ORDER_MIPS_OPTIONS
|
||||
ORDER_MIPS_ABI_FLAGS = TargetLayout<ELFT>::ORDER_RO_NOTE + 1,
|
||||
ORDER_MIPS_REGINFO,
|
||||
ORDER_MIPS_OPTIONS,
|
||||
};
|
||||
|
||||
MipsTargetLayout(MipsLinkingContext &ctx);
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
...
|
|
@ -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: []
|
||||
...
|
|
@ -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: []
|
||||
...
|
|
@ -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
|
||||
...
|
|
@ -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
|
||||
...
|
|
@ -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: []
|
||||
|
||||
...
|
Loading…
Reference in New Issue