diff options
-rw-r--r-- | lld/ELF/Arch/Mips.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/Arch/MipsArchTree.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/SyntheticSections.cpp | 11 | ||||
-rw-r--r-- | lld/ELF/Writer.h | 1 | ||||
-rw-r--r-- | lld/test/ELF/mips-micro-plt.s | 48 |
5 files changed, 60 insertions, 4 deletions
diff --git a/lld/ELF/Arch/Mips.cpp b/lld/ELF/Arch/Mips.cpp index 8284dad5da1..0c1ca5c846a 100644 --- a/lld/ELF/Arch/Mips.cpp +++ b/lld/ELF/Arch/Mips.cpp @@ -191,8 +191,6 @@ template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType Type) const { return RelativeRel; } -static bool isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; } - template <class ELFT> void MIPS<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &) const { uint64_t VA = InX::Plt->getVA(); diff --git a/lld/ELF/Arch/MipsArchTree.cpp b/lld/ELF/Arch/MipsArchTree.cpp index 5255e893ea2..0cf62fdf55e 100644 --- a/lld/ELF/Arch/MipsArchTree.cpp +++ b/lld/ELF/Arch/MipsArchTree.cpp @@ -364,6 +364,8 @@ bool elf::isMipsN32Abi(const InputFile *F) { } } +bool elf::isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; } + bool elf::isMipsR6() { uint32_t Arch = Config->EFlags & EF_MIPS_ARCH; return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index cdb787d3fea..b0c4f65a038 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1621,7 +1621,16 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { Symbol *Sym = Ent.Sym; if (Sym->isInPlt() && Sym->NeedsPltAddr) ESym->st_other |= STO_MIPS_PLT; - + if (isMicroMips()) { + // Set STO_MIPS_MICROMIPS flag and less-significant bit for + // defined microMIPS symbols and shared symbols with PLT record. + if ((Sym->isDefined() && (Sym->StOther & STO_MIPS_MICROMIPS)) || + (Sym->isShared() && Sym->NeedsPltAddr)) { + if (StrTabSec.isDynamic()) + ESym->st_value |= 1; + ESym->st_other |= STO_MIPS_MICROMIPS; + } + } if (Config->Relocatable) if (auto *D = dyn_cast<Defined>(Sym)) if (isMipsPIC<ELFT>(D)) diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h index 7354319d508..9f6cff36f30 100644 --- a/lld/ELF/Writer.h +++ b/lld/ELF/Writer.h @@ -54,6 +54,7 @@ uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, llvm::StringRef FileName); bool isMipsN32Abi(const InputFile *F); +bool isMicroMips(); bool isMipsR6(); } // namespace elf } // namespace lld diff --git a/lld/test/ELF/mips-micro-plt.s b/lld/test/ELF/mips-micro-plt.s index 195ce212501..5671dc420c5 100644 --- a/lld/test/ELF/mips-micro-plt.s +++ b/lld/test/ELF/mips-micro-plt.s @@ -6,10 +6,56 @@ # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ # RUN: -mattr=micromips %s -o %t-exe.o # RUN: ld.lld %t-exe.o %t.so -o %t.exe -# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck %s +# RUN: llvm-readobj -t -dt -mips-plt-got %t.exe | FileCheck %s # REQUIRES: mips +# CHECK: Symbols [ +# CHECK: Symbol { +# CHECK: Name: foo +# CHECK-NEXT: Value: 0x20008 +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other [ +# CHECK-NEXT: STO_MIPS_MICROMIPS +# CHECK-NEXT: STV_HIDDEN +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK: Symbol { +# CHECK: Name: __start +# CHECK-NEXT: Value: 0x20000 +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other [ +# CHECK-NEXT: STO_MIPS_MICROMIPS +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK: Symbol { +# CHECK: Name: foo0 +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: ] +# CHECK: DynamicSymbols [ +# CHECK: Symbol { +# CHECK: Name: foo0 +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: ] + # CHECK: Primary GOT { # CHECK: Local entries [ # CHECK-NEXT: Entry { |