From f967f090b830d1ae2547207e3311b877a2e0466a Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Thu, 29 Sep 2016 12:58:36 +0000 Subject: [PATCH] [ELF][MIPS] Setup STO_MIPS_PIC flag for PIC symbols when generate a relocatable object In case of linking PIC and non-PIC code together and generation of a relocatable object, all PIC symbols should have STO_MIPS_PIC flag in the symbol table of the ouput file. llvm-svn: 282714 --- lld/ELF/OutputSections.cpp | 20 +++++++++----- lld/ELF/Symbols.cpp | 12 +++++++++ lld/ELF/Symbols.h | 3 +++ lld/ELF/Target.cpp | 7 +---- lld/test/ELF/mips-sto-pic-flag.s | 58 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 lld/test/ELF/mips-sto-pic-flag.s diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 7bc09ef..feb7cad 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -1467,13 +1467,19 @@ void SymbolTableSection::writeGlobalSymbols(uint8_t *Buf) { else if (isa>(Body)) ESym->st_shndx = SHN_ABS; - // On MIPS we need to mark symbol which has a PLT entry and requires pointer - // equality by STO_MIPS_PLT flag. That is necessary to help dynamic linker - // distinguish such symbols and MIPS lazy-binding stubs. - // https://sourceware.org/ml/binutils/2008-07/txt00000.txt - if (Config->EMachine == EM_MIPS && Body->isInPlt() && - Body->NeedsCopyOrPltAddr) - ESym->st_other |= STO_MIPS_PLT; + if (Config->EMachine == EM_MIPS) { + // On MIPS we need to mark symbol which has a PLT entry and requires + // pointer equality by STO_MIPS_PLT flag. That is necessary to help + // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. + // https://sourceware.org/ml/binutils/2008-07/txt00000.txt + if (Body->isInPlt() && Body->NeedsCopyOrPltAddr) + ESym->st_other |= STO_MIPS_PLT; + if (Config->Relocatable) { + auto *D = dyn_cast>(Body); + if (D && D->isMipsPIC()) + ESym->st_other |= STO_MIPS_PIC; + } + } ++ESym; } } diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 94a3622..4819bb17 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -190,6 +190,13 @@ Defined::Defined(Kind K, StringRef Name, uint8_t StOther, uint8_t Type) Defined::Defined(Kind K, uint32_t NameOffset, uint8_t StOther, uint8_t Type) : SymbolBody(K, NameOffset, StOther, Type) {} +template bool DefinedRegular::isMipsPIC() const { + if (!Section || !isFunc()) + return false; + return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC || + (Section->getFile()->getObj().getHeader()->e_flags & EF_MIPS_PIC); +} + Undefined::Undefined(StringRef Name, uint8_t StOther, uint8_t Type, InputFile *File) : SymbolBody(SymbolBody::UndefinedKind, Name, StOther, Type) { @@ -315,6 +322,11 @@ template uint32_t SymbolBody::template getSize() const; template uint64_t SymbolBody::template getSize() const; template uint64_t SymbolBody::template getSize() const; +template class elf::DefinedRegular; +template class elf::DefinedRegular; +template class elf::DefinedRegular; +template class elf::DefinedRegular; + template class elf::DefinedSynthetic; template class elf::DefinedSynthetic; template class elf::DefinedSynthetic; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index c067e9c..c451edd 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -214,6 +214,9 @@ public: this->File = F; } + // Return true if the symbol is a PIC function. + bool isMipsPIC() const; + static bool classof(const SymbolBody *S) { return S->kind() == SymbolBody::DefinedRegularKind; } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index fb9c648..51dcc50 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -2054,14 +2054,9 @@ RelExpr MipsTargetInfo::getThunkExpr(RelExpr Expr, uint32_t Type, if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC) return Expr; auto *D = dyn_cast>(&S); - if (!D || !D->Section) - return Expr; // LA25 is required if target file has PIC code // or target symbol is a PIC symbol. - const ELFFile &DefFile = D->Section->getFile()->getObj(); - bool PicFile = DefFile.getHeader()->e_flags & EF_MIPS_PIC; - bool PicSym = (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC; - return (PicFile || PicSym) ? R_THUNK_ABS : Expr; + return D && D->isMipsPIC() ? R_THUNK_ABS : Expr; } template diff --git a/lld/test/ELF/mips-sto-pic-flag.s b/lld/test/ELF/mips-sto-pic-flag.s new file mode 100644 index 0000000..4d79233 --- /dev/null +++ b/lld/test/ELF/mips-sto-pic-flag.s @@ -0,0 +1,58 @@ +# In case of linking PIC and non-PIC code together and generation +# of a relocatable object, all PIC symbols should have STO_MIPS_PIC +# flag in the symbol table of the ouput file. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-npic.o +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ +# RUN: %p/Inputs/mips-pic.s -o %t-pic.o +# RUN: ld.lld -r %t-npic.o %t-pic.o -o %t-rel.o +# RUN: llvm-readobj -t %t-rel.o | FileCheck %s + +# REQUIRES: mips + +# CHECK: Symbol { +# CHECK: Name: main +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo1a +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other [ +# CHECK-NEXT: STO_MIPS_PIC +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo1b +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other [ +# CHECK-NEXT: STO_MIPS_PIC +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo2 +# CHECK-NEXT: Value: +# CHECK-NEXT: Size: +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other [ +# CHECK-NEXT: STO_MIPS_PIC +# CHECK-NEXT: ] +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } + + .text +main: + nop -- 2.7.4