diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmELF.cxx | 6 | ||||
-rw-r--r-- | Source/cmELF.h | 2 | ||||
-rw-r--r-- | Source/cmSystemTools.cxx | 24 |
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++; } } |