diff --git a/NEWS b/NEWS index a5f7b813..bfdcae80 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,11 @@ User visible changes for UPX Changes in 2.90 (xx Aug 2006): * vmlinuz/386: fixed zlib uncompression problem on dos + * new executable format BSD/elf386 supports FreeBSD, NetBSD, OpenBSD [how?] + * lzma algorithm support (--lzma; --brute [?]) + +Changes in 2.02 (xx Aug 2006): + * work around Linux kernel bug (".bss" requires PF_W) Changes in 2.01 (06 Jun 2006): * arm/pe: better DLL support diff --git a/README.SRC b/README.SRC index 9a608860..99913160 100644 --- a/README.SRC +++ b/README.SRC @@ -121,6 +121,8 @@ If you want to modify the stub sources you'll also need - Other cross compilers targeted at the following architectures. - arm-9tdmi-linux-gnu + - arm-unknown-linux-gnu-gcc-4.1.0 + [via crosstool-0.42 using gcc-4.1.0-glibc-2.3.2.dat] - powerpc-750-linux-gnu - x86_64-unknown-linux-gnu See http://upx.sourceforge.net/download/tools/ for pre-compiled diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index ca6e1b8a..d95a2ddb 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -50,15 +50,10 @@ int PackLinuxElf32::checkEhdr(Elf32_Ehdr const *ehdr) const { const unsigned char * const buf = ehdr->e_ident; - unsigned osabi0 = buf[Elf32_Ehdr::EI_OSABI]; - if (0==osabi0) { - osabi0 = opt->o_unix.osabi0; - } if (0!=memcmp(buf, "\x7f\x45\x4c\x46", 4) // "\177ELF" || buf[Elf32_Ehdr::EI_CLASS]!=ei_class || buf[Elf32_Ehdr::EI_DATA] !=ei_data - || osabi0!=ei_osabi ) { return -1; } @@ -146,7 +141,7 @@ PackLinuxElf64::checkEhdr(Elf64_Ehdr const *ehdr) const PackLinuxElf::PackLinuxElf(InputFile *f) : super(f), file_image(NULL), dynstr(NULL), sz_phdrs(0), sz_elf_hdrs(0), - e_machine(0), ei_class(0), ei_data(0), ei_osabi(0) + e_machine(0), ei_class(0), ei_data(0), ei_osabi(0), osabi_note(NULL) { } @@ -825,20 +820,42 @@ bool PackLinuxElf32::canPack() return false; } + unsigned osabi0 = buf[Elf32_Ehdr::EI_OSABI]; // The first PT_LOAD32 must cover the beginning of the file (0==p_offset). unsigned const e_phnum = get_native16(&ehdr->e_phnum); Elf32_Phdr const *phdr = (Elf32_Phdr const *)(buf + e_phoff); for (unsigned j=0; j < e_phnum; ++phdr, ++j) { if (j >= 14) - return false; - if (phdr->PT_LOAD32 == get_native32(&phdr->p_type)) { + return false; + if (1!=exetype && phdr->PT_LOAD32 == get_native32(&phdr->p_type)) { if (phdr->p_offset != 0) { throwCantPack("invalid Phdr p_offset; try `--force-execve'"); return false; } exetype = 1; - break; } + if (Elf32_Ehdr::ELFOSABI_NONE==osabi0 // Still seems to be generic. + && NULL!=osabi_note && phdr->PT_NOTE == get_native32(&phdr->p_type)) { + unsigned const offset = get_native32(&phdr->p_offset); + struct Elf32_Note note; memset(¬e, 0, sizeof(note)); + fi->seek(offset, SEEK_SET); + fi->readx(¬e, sizeof(note)); + fi->seek(0, SEEK_SET); + if (4==get_native32(¬e.descsz) + && 1==get_native32(¬e.type) + && 0==note.end + && (1+ strlen(osabi_note))==get_native32(¬e.namesz) + && 0==strcmp(osabi_note, (char const *)¬e.text) + ) { + osabi0 = ei_osabi; // Specified by PT_NOTE. + } + } + } + if (Elf32_Ehdr::ELFOSABI_NONE==osabi0) { // No EI_OSBAI, no PT_NOTE. + osabi0 = opt->o_unix.osabi0; // Possibly specified by command-line. + } + if (osabi0!=ei_osabi) { + return false; } // We want to compress position-independent executable (gcc -pie) @@ -1937,6 +1954,7 @@ PackFreeBSDElf32x86::~PackFreeBSDElf32x86() PackNetBSDElf32x86::PackNetBSDElf32x86(InputFile *f) : super(f) { ei_osabi = Elf32_Ehdr::ELFOSABI_NETBSD; + osabi_note = "NetBSD"; } PackNetBSDElf32x86::~PackNetBSDElf32x86() @@ -1946,6 +1964,7 @@ PackNetBSDElf32x86::~PackNetBSDElf32x86() PackOpenBSDElf32x86::PackOpenBSDElf32x86(InputFile *f) : super(f) { ei_osabi = Elf32_Ehdr::ELFOSABI_OPENBSD; + osabi_note = "OpenBSD"; } PackOpenBSDElf32x86::~PackOpenBSDElf32x86() diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index 1c31483c..d1550071 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -76,6 +76,7 @@ protected: unsigned char ei_class; unsigned char ei_data; unsigned char ei_osabi; + char const *osabi_note; }; class PackLinuxElf32 : public PackLinuxElf