[MIPS] Set STO_MIPS_MICROMIPS flag and less-significant bit for microMIPS symbols

microMIPS symbols including microMIPS PLT records created for regular
symbols needs to be marked by STO_MIPS_MICROMIPS flag in a symbol table.
Additionally microMIPS entries in a dynamic symbol table should have
configured less-significant bit. That allows to escape teaching a
dynamic linker about microMIPS symbols.

llvm-svn: 318097
This commit is contained in:
Simon Atanasyan 2017-11-13 22:40:36 +00:00
parent 87d196ca48
commit cfa8aa7edb
5 changed files with 60 additions and 4 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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))

View File

@ -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

View File

@ -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 {