Bläddra i källkod

cmSystemTools, elf: handle DT_MIPS_RLD_REL_MAP in RemoveRPath

James Cowgill 9 år sedan
förälder
incheckning
cd4f573ae9
3 ändrade filer med 31 tillägg och 1 borttagningar
  1. 6 0
      Source/cmELF.cxx
  2. 1 1
      Source/cmELF.h
  3. 24 0
      Source/cmSystemTools.cxx

+ 6 - 0
Source/cmELF.cxx

@@ -700,6 +700,12 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString(
 const long cmELF::TagRPath = DT_RPATH;
 const long cmELF::TagRunPath = DT_RUNPATH;
 
+#ifdef DT_MIPS_RLD_MAP_REL
+const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL;
+#else
+const long cmELF::TagMipsRldMapRel = 0;
+#endif
+
 cmELF::cmELF(const char* fname)
   : Internal(CM_NULLPTR)
 {

+ 1 - 1
Source/cmELF.h

@@ -107,7 +107,7 @@ public:
 
   /** Interesting dynamic tags.
       If the tag is 0, it does not exist in the host ELF implementation */
-  static const long TagRPath, TagRunPath;
+  static const long TagRPath, TagRunPath, TagMipsRldMapRel;
 
 private:
   friend class cmELFInternal;

+ 24 - 0
Source/cmSystemTools.cxx

@@ -2536,6 +2536,10 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
       zeroSize[i] = se[i]->Size;
     }
 
+    // Get size of one DYNAMIC entry
+    unsigned long const sizeof_dentry =
+      elf.GetDynamicEntryPosition(1) - elf.GetDynamicEntryPosition(0);
+
     // Adjust the entry list as necessary to remove the run path
     unsigned long entriesErased = 0;
     for (cmELF::DynamicEntryList::iterator it = dentries.begin();
@@ -2545,6 +2549,26 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
         entriesErased++;
         continue;
       } else {
+        if (cmELF::TagMipsRldMapRel != 0 &&
+            it->first == cmELF::TagMipsRldMapRel) {
+          // Background: debuggers need to know the "linker map" which contains
+          // the addresses each dynamic object is loaded at. Most arches use
+          // the DT_DEBUG tag which the dynamic linker writes to (directly) and
+          // contain the location of the linker map, however on MIPS the
+          // .dynamic section is always read-only so this is not possible. MIPS
+          // objects instead contain a DT_MIPS_RLD_MAP tag which contains the
+          // address where the dyanmic linker will write to (an indirect
+          // version of DT_DEBUG). Since this doesn't work when using PIE, a
+          // relative equivalent was created - DT_MIPS_RLD_MAP_REL. Since this
+          // version contains a relative offset, moving it changes the
+          // calculated address. This may cause the dyanmic linker to write
+          // into memory it should not be changing.
+          //
+          // To fix this, we adjust the value of DT_MIPS_RLD_MAP_REL here. If
+          // we move it up by n bytes, we add n bytes to the value of this tag.
+          it->second += entriesErased * sizeof_dentry;
+        }
+
         it++;
       }
     }