Index: ELF/Arch/Mips.cpp =================================================================== --- ELF/Arch/Mips.cpp +++ ELF/Arch/Mips.cpp @@ -238,37 +238,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 Config->MipsEFlags & 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 = Config->MipsEFlags & 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 @@ -310,11 +302,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 @@ -332,8 +324,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 uint32_t elf::calcMipsEFlags() { std::vector V; for (InputFile *F : ObjectFiles) V.push_back( @@ -364,7 +364,7 @@ } } -template uint32_t elf::getMipsEFlags(); -template uint32_t elf::getMipsEFlags(); -template uint32_t elf::getMipsEFlags(); -template uint32_t elf::getMipsEFlags(); +template uint32_t elf::calcMipsEFlags(); +template uint32_t elf::calcMipsEFlags(); +template uint32_t elf::calcMipsEFlags(); +template uint32_t elf::calcMipsEFlags(); 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::calcMipsEFlags` 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/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1080,6 +1080,9 @@ for (InputSectionBase *S : F->getSections()) InputSections.push_back(cast(S)); + if (Config->EMachine == EM_MIPS) + Config->MipsEFlags = calcMipsEFlags(); + // This adds a .comment section containing a version string. We have to add it // before decompressAndMergeSections because the .comment section is a // mergeable section. Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -144,7 +144,7 @@ return nullptr; } - // LLD checks ISA compatibility in getMipsEFlags(). Here we just + // LLD checks ISA compatibility in calcMipsEFlags(). Here we just // select the highest number of ISA/Rev/Ext. Flags.isa_level = std::max(Flags.isa_level, S->isa_level); Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev); Index: ELF/Writer.h =================================================================== --- ELF/Writer.h +++ ELF/Writer.h @@ -48,7 +48,7 @@ llvm::StringRef getOutputSectionName(llvm::StringRef Name); -template uint32_t getMipsEFlags(); +template uint32_t calcMipsEFlags(); uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, llvm::StringRef FileName); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1806,7 +1806,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 = Config->MipsEFlags; 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