Index: ELF/Arch/Mips.cpp =================================================================== --- ELF/Arch/Mips.cpp +++ ELF/Arch/Mips.cpp @@ -215,37 +215,29 @@ write16(Loc, Data); } -template static bool isMicroMips() { - // FIXME (simon): This code does not support the case when both - // microMIPS and MIPS object files are linked together. - const auto &FirstObj = cast>(*Config->FirstElf); - uint32_t Arch = FirstObj.getObj().getHeader()->e_flags & EF_MIPS_ARCH_ASE; - return Arch == EF_MIPS_MICROMIPS; -} +static bool isMicroMips() { return getMipsEFlags() & EF_MIPS_MICROMIPS; } -template static bool isMipsR6() { - const auto &FirstObj = cast>(*Config->FirstElf); - uint32_t Arch = FirstObj.getObj().getHeader()->e_flags & EF_MIPS_ARCH; +static bool isMipsR6() { + uint32_t Arch = getMipsEFlags() & EF_MIPS_ARCH; return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; } template void MIPS::writePltHeader(uint8_t *Buf) const { const endianness E = ELFT::TargetEndianness; - if (isMicroMips()) { + if (isMicroMips()) { uint64_t GotPlt = In::GotPlt->getVA(); uint64_t Plt = In::Plt->getVA(); // Overwrite trap instructions written by Writer::writeTrapInstr. memset(Buf, 0, PltHeaderSize); - write16(Buf, isMipsR6() ? 0x7860 : 0x7980); - // addiupc v1, (GOTPLT) - . + write16(Buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - . write16(Buf + 4, 0xff23); // lw $25, 0($3) write16(Buf + 8, 0x0535); // subu16 $2, $2, $3 write16(Buf + 10, 0x2525); // srl16 $2, $2, 2 write16(Buf + 12, 0x3302); // addiu $24, $2, -2 write16(Buf + 14, 0xfffe); write16(Buf + 16, 0x0dff); // move $15, $31 - if (isMipsR6()) { + if (isMipsR6()) { write16(Buf + 18, 0x0f83); // move $28, $3 write16(Buf + 20, 0x472b); // jalrc $25 write16(Buf + 22, 0x0c00); // nop @@ -287,11 +279,11 @@ uint64_t PltEntryAddr, int32_t Index, unsigned RelOff) const { const endianness E = ELFT::TargetEndianness; - if (isMicroMips()) { + if (isMicroMips()) { // Overwrite trap instructions written by Writer::writeTrapInstr. memset(Buf, 0, PltEntrySize); - if (isMipsR6()) { + if (isMipsR6()) { write16(Buf, 0x7840); // addiupc $2, (GOTPLT) - . write16(Buf + 4, 0xff22); // lw $25, 0($2) write16(Buf + 8, 0x0f02); // move $24, $2 @@ -309,8 +301,7 @@ write32(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry) write32(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15) - // jr $25 - write32(Buf + 8, isMipsR6() ? 0x03200009 : 0x03200008); + write32(Buf + 8, isMipsR6() ? 0x03200009 : 0x03200008); // jr $25 write32(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry) writeRelocation(Buf, GotPltEntryAddr + 0x8000, 16, 16); writeRelocation(Buf + 4, GotPltEntryAddr, 16, 0); Index: ELF/Arch/MipsArchTree.cpp =================================================================== --- ELF/Arch/MipsArchTree.cpp +++ ELF/Arch/MipsArchTree.cpp @@ -281,7 +281,7 @@ return Ret; } -template uint32_t elf::getMipsEFlags() { +template static uint32_t calcMipsEFlags() { std::vector V; for (ObjFile *F : ObjFile::Instances) V.push_back({F->getName(), F->getObj().getHeader()->e_flags}); @@ -291,6 +291,28 @@ return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V); } +uint32_t elf::getMipsEFlags() { + if (!Config->MipsEFlags) { + switch (Config->EKind) { + case ELF32LEKind: + Config->MipsEFlags = calcMipsEFlags(); + break; + case ELF32BEKind: + Config->MipsEFlags = calcMipsEFlags(); + break; + case ELF64LEKind: + Config->MipsEFlags = calcMipsEFlags(); + break; + case ELF64BEKind: + Config->MipsEFlags = calcMipsEFlags(); + break; + default: + llvm_unreachable("unknown Config->EKind"); + } + } + return Config->MipsEFlags; +} + static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) { if (FpA == FpB) return 0; @@ -362,8 +384,3 @@ llvm_unreachable("unknown Config->EKind"); } } - -template uint32_t elf::getMipsEFlags(); -template uint32_t elf::getMipsEFlags(); -template uint32_t elf::getMipsEFlags(); -template uint32_t elf::getMipsEFlags(); Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -211,6 +211,12 @@ // if that's true.) bool IsMips64EL; + // Holds set of ELF header flags for MIPS targets. The set calculated + // by the `elf::getMipsEFlags` function and cashed in this field. For + // the calculation we iterate over all input object files and combine + // their ELF flags. + uint32_t MipsEFlags = 0; + // The ELF spec defines two types of relocation table entries, RELA and // REL. RELA is a triplet of (offset, info, addend) while REL is a // tuple of (offset, info). Addends for REL are implicit and read from Index: ELF/Writer.h =================================================================== --- ELF/Writer.h +++ ELF/Writer.h @@ -48,7 +48,7 @@ llvm::StringRef getOutputSectionName(llvm::StringRef Name); -template uint32_t getMipsEFlags(); +uint32_t getMipsEFlags(); uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, llvm::StringRef FileName); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1796,7 +1796,7 @@ // kernels (as of 2016) require an EABI version to be set. EHdr->e_flags = EF_ARM_EABI_VER5; else if (Config->EMachine == EM_MIPS) - EHdr->e_flags = getMipsEFlags(); + EHdr->e_flags = getMipsEFlags(); if (!Config->Relocatable) { EHdr->e_phoff = sizeof(Elf_Ehdr); Index: test/ELF/mips-elf-flags.s =================================================================== --- test/ELF/mips-elf-flags.s +++ test/ELF/mips-elf-flags.s @@ -35,6 +35,12 @@ # RUN: llvm-readobj -h -mips-abi-flags %t.exe \ # RUN: | FileCheck -check-prefix=OCTEON %s +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ +# RUN: -mattr=micromips %S/Inputs/mips-fpic.s -o %t-mm.o +# RUN: ld.lld %t.o %t-mm.o -o %t.exe +# RUN: llvm-readobj -h -mips-abi-flags %t.exe | FileCheck -check-prefix=MICRO %s + # REQUIRES: mips .text @@ -170,3 +176,26 @@ # OCTEON-NEXT: ] # OCTEON-NEXT: Flags 2: 0x0 # OCTEON-NEXT: } + +# MICRO: Flags [ +# MICRO-NEXT: EF_MIPS_ABI_O32 +# MICRO-NEXT: EF_MIPS_ARCH_32 +# MICRO-NEXT: EF_MIPS_CPIC +# MICRO-NEXT: EF_MIPS_MICROMIPS +# MICRO-NEXT: ] +# MICRO: MIPS ABI Flags { +# MICRO-NEXT: Version: 0 +# MICRO-NEXT: ISA: MIPS32 +# MICRO-NEXT: ISA Extension: None +# MICRO-NEXT: ASEs [ +# MICRO-NEXT: microMIPS +# MICRO-NEXT: ] +# MICRO-NEXT: FP ABI: Hard float (double precision) +# MICRO-NEXT: GPR size: 32 +# MICRO-NEXT: CPR1 size: 32 +# MICRO-NEXT: CPR2 size: 0 +# MICRO-NEXT: Flags 1 [ +# MICRO-NEXT: ODDSPREG +# MICRO-NEXT: ] +# MICRO-NEXT: Flags 2: 0x0 +# MICRO-NEXT: } Index: test/ELF/mips-micro-jal.s =================================================================== --- test/ELF/mips-micro-jal.s +++ test/ELF/mips-micro-jal.s @@ -34,6 +34,17 @@ # RUN: ld.lld -o %tel.exe %t2el.o %tel.so # RUN: llvm-objdump -d -mattr=micromips %tel.exe | FileCheck --check-prefix=ELR6 %s +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ +# RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1eb.o +# RUN: ld.lld -shared -o %teb.so %t1eb.o +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ +# RUN: %S/Inputs/mips-fpic.s -o %t-reg.o +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ +# RUN: -mattr=micromips %s -o %t2eb.o +# RUN: ld.lld --no-threads -o %teb.exe %t-reg.o %t2eb.o %teb.so +# RUN: llvm-objdump -d -mattr=micromips %teb.exe \ +# RUN: | FileCheck --check-prefix=MIXED %s + # REQUIRES: mips # EB: Disassembly of section .plt: @@ -106,6 +117,25 @@ # ELR6-NEXT: 20038: 02 0f move16 $24, $2 # ELR6-NEXT: 2003a: 23 47 jrc16 $25 +# MIXED: Disassembly of section .plt: +# MIXED-NEXT: .plt: +# MIXED-NEXT: 20020: 79 80 3f f9 addiupc $3, 65508 +# MIXED-NEXT: 20024: ff 23 00 00 lw $25, 0($3) +# MIXED-NEXT: 20028: 05 35 subu16 $2, $2, $3 +# MIXED-NEXT: 2002a: 25 25 srl16 $2, $2, 2 +# MIXED-NEXT: 2002c: 33 02 ff fe addiu $24, $2, -2 +# MIXED-NEXT: 20030: 0d ff move $15, $ra +# MIXED-NEXT: 20032: 45 f9 jalrs16 $25 +# MIXED-NEXT: 20034: 0f 83 move $gp, $3 +# MIXED-NEXT: 20036: 0c 00 nop +# MIXED-NEXT: 20038: 00 00 00 00 nop +# MIXED-NEXT: 2003c: 00 00 00 00 nop + +# MIXED-NEXT: 20040: 79 00 3f f3 addiupc $2, 65484 +# MIXED-NEXT: 20044: ff 22 00 00 lw $25, 0($2) +# MIXED-NEXT: 20048: 45 99 jr16 $25 +# MIXED-NEXT: 2004a: 0f 02 move $24, $2 + # PLT: Entries [ # PLT-NEXT: Entry { # PLT-NEXT: Address: 0x3000C