[ELF][MIPS] Setup STO_MIPS_PIC flag for PIC symbols when generate a relocatable object
authorSimon Atanasyan <simon@atanasyan.com>
Thu, 29 Sep 2016 12:58:36 +0000 (12:58 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Thu, 29 Sep 2016 12:58:36 +0000 (12:58 +0000)
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
lld/ELF/Symbols.cpp
lld/ELF/Symbols.h
lld/ELF/Target.cpp
lld/test/ELF/mips-sto-pic-flag.s [new file with mode: 0644]

index 7bc09ef..feb7cad 100644 (file)
@@ -1467,13 +1467,19 @@ void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) {
     else if (isa<DefinedRegular<ELFT>>(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<DefinedRegular<ELFT>>(Body);
+        if (D && D->isMipsPIC())
+          ESym->st_other |= STO_MIPS_PIC;
+      }
+    }
     ++ESym;
   }
 }
index 94a3622..4819bb1 100644 (file)
@@ -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 <class ELFT> bool DefinedRegular<ELFT>::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<ELF32BE>() const;
 template uint64_t SymbolBody::template getSize<ELF64LE>() const;
 template uint64_t SymbolBody::template getSize<ELF64BE>() const;
 
+template class elf::DefinedRegular<ELF32LE>;
+template class elf::DefinedRegular<ELF32BE>;
+template class elf::DefinedRegular<ELF64LE>;
+template class elf::DefinedRegular<ELF64BE>;
+
 template class elf::DefinedSynthetic<ELF32LE>;
 template class elf::DefinedSynthetic<ELF32BE>;
 template class elf::DefinedSynthetic<ELF64LE>;
index c067e9c..c451edd 100644 (file)
@@ -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;
   }
index fb9c648..51dcc50 100644 (file)
@@ -2054,14 +2054,9 @@ RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
   if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)
     return Expr;
   auto *D = dyn_cast<DefinedRegular<ELFT>>(&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<ELFT> &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 <class ELFT>
diff --git a/lld/test/ELF/mips-sto-pic-flag.s b/lld/test/ELF/mips-sto-pic-flag.s
new file mode 100644 (file)
index 0000000..4d79233
--- /dev/null
@@ -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