[Mips] Handle R_MIPS_COPY relocation.
authorSimon Atanasyan <simon@atanasyan.com>
Tue, 11 Feb 2014 05:34:02 +0000 (05:34 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Tue, 11 Feb 2014 05:34:02 +0000 (05:34 +0000)
llvm-svn: 201129

lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
lld/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
lld/test/elf/Mips/rcopy.test [new file with mode: 0644]

index 43578d5..80343ff 100644 (file)
@@ -46,6 +46,19 @@ void MipsLinkingContext::addPasses(PassManager &pm) {
   ELFLinkingContext::addPasses(pm);
 }
 
+bool MipsLinkingContext::isDynamicRelocation(const DefinedAtom &,
+                                             const Reference &r) const {
+  if (r.kindNamespace() != Reference::KindNamespace::ELF)
+    return false;
+
+  switch (r.kindValue()) {
+  case llvm::ELF::R_MIPS_COPY:
+    return true;
+  default:
+    return false;
+  }
+}
+
 bool MipsLinkingContext::isPLTRelocation(const DefinedAtom &,
                                          const Reference &r) const {
   if (r.kindNamespace() != Reference::KindNamespace::ELF)
index 17b4219..f44ff7f 100644 (file)
@@ -46,6 +46,8 @@ public:
   virtual StringRef getDefaultInterpreter() const;
   virtual void addPasses(PassManager &pm);
   virtual bool isRelaOutputFormat() const { return false; }
+  virtual bool isDynamicRelocation(const DefinedAtom &,
+                                   const Reference &r) const;
   virtual bool isPLTRelocation(const DefinedAtom &, const Reference &r) const;
 };
 
index 3ec98c6..78c879f 100644 (file)
@@ -155,6 +155,11 @@ public:
       gotplt->setOrdinal(ordinal++);
       mf->addAtom(*gotplt);
     }
+
+    for (auto obj : _objectVector) {
+      obj->setOrdinal(ordinal++);
+      mf->addAtom(*obj);
+    }
   }
 
 private:
@@ -176,18 +181,30 @@ private:
   /// \brief Map Atoms to their PLT entries.
   llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
 
+  /// \brief Map Atoms to their Object entries.
+  llvm::DenseMap<const Atom *, ObjectAtom *> _objectMap;
+
   /// \brief the list of PLT atoms.
   std::vector<PLTAtom *> _pltVector;
 
   /// \brief the list of GOTPLT atoms.
   std::vector<GOTAtom *> _gotpltVector;
 
+  /// \brief the list of Object entries.
+  std::vector<ObjectAtom *> _objectVector;
+
   /// \brief Handle a specific reference.
   void handleReference(const DefinedAtom &atom, const Reference &ref) {
     if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
       return;
     assert(ref.kindArch() == Reference::KindArch::Mips);
     switch (ref.kindValue()) {
+    case R_MIPS_32:
+    case R_MIPS_HI16:
+    case R_MIPS_LO16:
+      // FIXME (simon): Handle dynamic/static linking differently.
+      handlePlain(ref);
+      break;
     case R_MIPS_26:
       handlePLT(ref);
       break;
@@ -204,6 +221,14 @@ private:
     return false;
   }
 
+  void handlePlain(const Reference &ref) {
+    if (!ref.target())
+      return;
+    auto sla = dyn_cast<SharedLibraryAtom>(ref.target());
+    if (sla && sla->type() == SharedLibraryAtom::Type::Data)
+      const_cast<Reference &>(ref).setTarget(getObjectEntry(sla));
+  }
+
   void handlePLT(const Reference &ref) {
     if (ref.kindValue() == R_MIPS_26 && !isLocal(ref.target()))
       const_cast<Reference &>(ref).setKindValue(LLD_R_MIPS_GLOBAL_26);
@@ -332,6 +357,22 @@ private:
 
     return pa;
   }
+
+  const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a) {
+    auto obj = _objectMap.find(a);
+    if (obj != _objectMap.end())
+      return obj->second;
+
+    auto oa = new (_file._alloc) ObjectAtom(_file);
+    oa->addReferenceELF_Mips(R_MIPS_COPY, 0, oa, 0);
+    oa->_name = a->name();
+    oa->_size = a->size();
+
+    _objectMap[a] = oa;
+    _objectVector.push_back(oa);
+
+    return oa;
+  }
 };
 
 } // end anon namespace
index be3d1e4..84ee963 100644 (file)
@@ -56,6 +56,7 @@ const Registry::KindStrings MipsTargetHandler::kindStrings[] = {
   LLD_KIND_STRING_ENTRY(R_MIPS_GOT16),
   LLD_KIND_STRING_ENTRY(R_MIPS_CALL16),
   LLD_KIND_STRING_ENTRY(R_MIPS_JALR),
+  LLD_KIND_STRING_ENTRY(R_MIPS_COPY),
   LLD_KIND_STRING_ENTRY(R_MIPS_JUMP_SLOT),
   LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT),
   LLD_KIND_STRING_ENTRY(LLD_R_MIPS_GLOBAL_GOT16),
diff --git a/lld/test/elf/Mips/rcopy.test b/lld/test/elf/Mips/rcopy.test
new file mode 100644 (file)
index 0000000..5184959
--- /dev/null
@@ -0,0 +1,42 @@
+# Check handling of R_MIPS_COPY relocation
+
+# Build shared library
+# RUN: llvm-mc -triple=mipsel -filetype=obj -relocation-model=pic \
+# RUN:         -o=%t-obj %p/Inputs/ext.s
+# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-obj
+
+# Build executable
+# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s
+# RUN: lld -flavor gnu -target mipsel -e glob -o %t %t-obj %t-so
+# RUN: llvm-readobj -relocations -symbols -dyn-symbols %t | FileCheck %s
+
+# CHECK:       Relocations [
+# CHECK-NEXT:    Section ({{[0-9]+}}) .rel.dyn {
+# CHECK-NEXT:      0x{{[1-9A-F][0-9A-F]*}} R_MIPS_COPY data1 0x0
+# CHECK-NEXT:    }
+# CHECK-NEXT:  ]
+
+# CHECK:         Name: data1 ({{[0-9]+}}
+# CHECK-NEXT:    Value: 0x{{[1-9A-F][0-9A-F]*}}
+# CHECK-NEXT:    Size: 4
+# CHECK-NEXT:    Binding: Global (0x1)
+# CHECK-NEXT:    Type: Object (0x1)
+# CHECK-NEXT:    Other: 0
+# CHECK-NEXT:    Section: .bss (0x{{[1-9A-F][0-9A-F]*}})
+
+# CHECK:         Name: data1@ ({{[0-9]+}}
+# CHECK-NEXT:    Value: 0x{{[1-9A-F][0-9A-F]*}}
+# CHECK-NEXT:    Size: 4
+# CHECK-NEXT:    Binding: Global (0x1)
+# CHECK-NEXT:    Type: Object (0x1)
+# CHECK-NEXT:    Other: 0
+# CHECK-NEXT:    Section: .bss (0x{{[1-9A-F][0-9A-F]*}})
+
+    .abicalls
+    .option pic0
+    .global glob
+    .ent    glob
+glob:
+    lui     $2,%hi(data1)
+    lw      $2,%lo(data1)($2)
+    .end    glob