diff --git a/src/main.cpp b/src/main.cpp index 12a5bb6f..db57160b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -692,6 +692,9 @@ static int do_option(int optc, const char *arg) if (mfx_optarg && mfx_optarg[0]) set_script_name(mfx_optarg,1); break; + case 663: + opt->unix.ptinterp = true; + break; case 670: opt->psx.no_align = true; break; @@ -802,6 +805,7 @@ static const struct mfx_option longopts[] = #if 0 {"script", 0x31, 0, 662}, // --script= #endif + {"ptinterp", 0, 0, 663}, // linux/elf386 PT_INTERP program // watcom/le {"le", 0, 0, 620}, // produce LE output // win32/pe diff --git a/src/options.h b/src/options.h index fb523d8e..659e9ce9 100644 --- a/src/options.h +++ b/src/options.h @@ -114,6 +114,7 @@ struct options_t { struct { unsigned blocksize; bool force_execve; // force the linux/386 execve format + bool ptinterp; // is PT_INTERP, so don't adjust auxv_t enum { SCRIPT_MAX = 32 }; const char *script_name; } unix; diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index c0b50aac..f715cd6e 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -78,9 +78,23 @@ PackLinuxI386elf::getFilters() const int PackLinuxI386elf::buildLoader(const Filter *ft) { + unsigned char tmp[sizeof(linux_i386elf_fold)]; + memcpy(tmp, linux_i386elf_fold, sizeof(linux_i386elf_fold)); + if (opt->unix.ptinterp) { + unsigned j; + for (j = 0; j < sizeof(linux_i386elf_fold)-1; ++j) { + if (0x60==tmp[ j] + && 0x47==tmp[1+j] ) { + /* put INC EDI before PUSHA: inhibits auxv_up for PT_INTERP */ + tmp[ j] = 0x47; + tmp[1+j] = 0x60; + break; + } + } + } return buildLinuxLoader( linux_i386elf_loader, sizeof(linux_i386elf_loader), - linux_i386elf_fold, sizeof(linux_i386elf_fold), ft ); + tmp, sizeof(linux_i386elf_fold), ft ); }