feat: add --no-clobber-old-sections switch

Works around #520, may be useful for other cursed self-modifying things.
This commit is contained in:
K900 2023-09-21 18:20:53 +03:00 committed by Jörg Thalheim
parent afd3cc9445
commit 917ea45b79
2 changed files with 24 additions and 8 deletions

View File

@ -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.

View File

@ -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;
@ -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 = {};
@ -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\
@ -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;