Skip to content

Commit

Permalink
feat: add --no-clobber-old-sections switch
Browse files Browse the repository at this point in the history
Works around NixOS#520, may be useful for other cursed self-modifying things.
  • Loading branch information
K900 committed Sep 27, 2023
1 parent afd3cc9 commit 4f710cb
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 8 deletions.
9 changes: 9 additions & 0 deletions patchelf.1
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ old_name new_name

Symbol names do not contain version specifier that are also shown in the output of the nm -D command from binutils. So instead of the name write@GLIBC_2.2.5 it is just write.

.IP "--no-clobber-old-sections"
Do not clobber old section values.

patchelf defaults to overwriting replaced header sections with garbage to ensure they are not
used accidentally. This option allows to opt out of that behavior, so that binaries that attempt
to read their own headers from a fixed offset (e.g. Firefox) continue working.

Use sparingly and with caution.

.IP "--output FILE"
Set the output file name. If not specified, the input will be modified in place.

Expand Down
23 changes: 15 additions & 8 deletions src/patchelf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
static bool debugMode = false;

static bool forceRPath = false;
static bool clobberOldSections = true;

static std::vector<std::string> fileNames;
static std::string outputFileName;
Expand Down Expand Up @@ -664,14 +665,16 @@ template<ElfFileParams>
void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
Elf_Addr startAddr, Elf_Off startOffset)
{
/* Overwrite the old section contents with 'Z's. Do this
*before* writing the new section contents (below) to prevent
clobbering previously written new section contents. */
for (auto & i : replacedSections) {
const std::string & sectionName = i.first;
const Elf_Shdr & shdr = findSectionHeader(sectionName);
if (rdi(shdr.sh_type) != SHT_NOBITS)
memset(fileContents->data() + rdi(shdr.sh_offset), 'Z', rdi(shdr.sh_size));
if (clobberOldSections) {
/* Overwrite the old section contents with 'Z's. Do this
*before* writing the new section contents (below) to prevent
clobbering previously written new section contents. */
for (auto & i : replacedSections) {
const std::string & sectionName = i.first;
const Elf_Shdr & shdr = findSectionHeader(sectionName);
if (rdi(shdr.sh_type) != SHT_NOBITS)
memset(fileContents->data() + rdi(shdr.sh_offset), 'Z', rdi(shdr.sh_size));
}
}

std::set<unsigned int> noted_phdrs = {};
Expand Down Expand Up @@ -2505,6 +2508,7 @@ static void showHelp(const std::string & progName)
[--clear-execstack]\n\
[--set-execstack]\n\
[--rename-dynamic-symbols NAME_MAP_FILE]\tRenames dynamic symbols. The map file should contain two symbols (old_name new_name) per line\n\
[--no-clobber-old-sections]\t\tDo not clobber old section values - only use when the binary expects to find section info at the old location.\n\
[--output FILE]\n\
[--debug]\n\
[--version]\n\
Expand Down Expand Up @@ -2661,6 +2665,9 @@ static int mainWrapped(int argc, char * * argv)
symbolsToRename[*symbolsToRenameKeys.insert(from).first] = to;
}
}
else if (arg == "--no-clobber-old-sections") {
clobberOldSections = false;
}
else if (arg == "--help" || arg == "-h" ) {
showHelp(argv[0]);
return 0;
Expand Down

0 comments on commit 4f710cb

Please sign in to comment.