Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/patchelf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1809,17 +1809,33 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(const std::map<std::string, std::
char * name = strTab + rdi(dyn->d_un.d_val);
auto i = libs.find(name);
if (i != libs.end() && name != i->second) {
auto orig = i->first;
auto replacement = i->second;

debug("replacing DT_NEEDED entry '%s' with '%s'\n", name, replacement.c_str());

auto a = addedStrings.find(replacement);
// the same replacement string has already been added, reuse it
if (a != addedStrings.end()) {
debug("reusing previous replacement\n");
wri(dyn->d_un.d_val, a->second);
continue;
}

// if the replacement a suffix of the original, e.g. when replacing full
// paths with the basename or stripping a sysroot-like prefix, then
// update the reference to that suffix while keeping the original
// intact (thus we can potentially avoid relocating the whole section
// which seems problematic at least on MIPS).
auto pos = orig.rfind(replacement);
if (pos != std::string::npos && orig.size() == pos + replacement.size()) {
debug("reusing suffix\n");
wri(dyn->d_un.d_val, rdi(dyn->d_un.d_val) + pos);
/* ensure write-out in case all replaces use this technique */
changed = true;
continue;
}

// technically, the string referred by d_val could be used otherwise, too (although unlikely)
// we'll therefore add a new string
debug("resizing .dynstr ...\n");
Expand Down