summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmELF.cxx6
-rw-r--r--Source/cmELF.h2
-rw-r--r--Source/cmSystemTools.cxx24
3 files changed, 31 insertions, 1 deletions
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index bf0130a..6f2885c 100644
--- a/Source/cmELF.cxx
+++ b/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)
{
diff --git a/Source/cmELF.h b/Source/cmELF.h
index 3fc59b4..9c56be7 100644
--- a/Source/cmELF.h
+++ b/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;
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 8951788..d800ef8 100644
--- a/Source/cmSystemTools.cxx
+++ b/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++;
}
}