From 9c564fd4c71e4fe7dc27a8ff9e75c28bb03dd6cd Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sun, 22 Apr 2007 16:09:18 -0700 Subject: [PATCH] Add file formst UPX_F_LINUX_ELF32_ARMEB and normalize spelling of ARMEL, ARMEB, armel, armeb. --- src/conf.h | 7 +-- src/p_lx_elf.h | 4 +- src/p_vmlinx.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++---- src/p_vmlinx.h | 32 ++++++++++++-- src/packer_c.cpp | 14 +++--- src/packmast.cpp | 4 +- src/stub/Makefile | 24 +++++++++++ 7 files changed, 169 insertions(+), 24 deletions(-) diff --git a/src/conf.h b/src/conf.h index 119d5147..7b9620f2 100644 --- a/src/conf.h +++ b/src/conf.h @@ -448,13 +448,13 @@ private: #define UPX_F_LINUX_ELFI_i386 20 #define UPX_F_WINCE_ARM_PE 21 #define UPX_F_LINUX_ELF64_AMD 22 -#define UPX_F_LINUX_ELF32_ARMLE 23 +#define UPX_F_LINUX_ELF32_ARMEL 23 #define UPX_F_BSD_i386 24 #define UPX_F_BSD_ELF_i386 25 #define UPX_F_BSD_SH_i386 26 #define UPX_F_VMLINUX_AMD64 27 -#define UPX_F_VMLINUX_ARM 28 +#define UPX_F_VMLINUX_ARMEL 28 #define UPX_F_MACH_i386 29 #define UPX_F_PLAIN_TEXT 127 @@ -463,8 +463,9 @@ private: #define UPX_F_SOLARIS_SPARC 130 #define UPX_F_MACH_PPC32 131 #define UPX_F_LINUX_ELFPPC32 132 -#define UPX_F_LINUX_ELF32_ARMBE 133 +#define UPX_F_LINUX_ELF32_ARMEB 133 #define UPX_F_MACH_FAT 134 +#define UPX_F_VMLINUX_ARMEB 135 // compression methods diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index f446cddc..fc8533d2 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -416,7 +416,7 @@ class PackLinuxElf32armLe : public PackLinuxElf32Le public: PackLinuxElf32armLe(InputFile *f); virtual ~PackLinuxElf32armLe(); - virtual int getFormat() const { return UPX_F_LINUX_ELF32_ARMLE; } + virtual int getFormat() const { return UPX_F_LINUX_ELF32_ARMEL; } virtual const char *getName() const { return "linux/armLE"; } virtual const char *getFullName(const options_t *) const { return "arm-linux.elf"; } virtual const int *getFilters() const; @@ -436,7 +436,7 @@ class PackLinuxElf32armBe : public PackLinuxElf32Be public: PackLinuxElf32armBe(InputFile *f); virtual ~PackLinuxElf32armBe(); - virtual int getFormat() const { return UPX_F_LINUX_ELF32_ARMBE; } + virtual int getFormat() const { return UPX_F_LINUX_ELF32_ARMEB; } virtual const char *getName() const { return "linux/armBE"; } virtual const char *getFullName(const options_t *) const { return "armeb-linux.elf"; } virtual const int *getFilters() const; diff --git a/src/p_vmlinx.cpp b/src/p_vmlinx.cpp index 7470627d..6b062d69 100644 --- a/src/p_vmlinx.cpp +++ b/src/p_vmlinx.cpp @@ -44,6 +44,8 @@ static const #include "stub/amd64-linux.kernel.vmlinux.h" static const #include "stub/arm-linux.kernel.vmlinux.h" +static const +#include "stub/armeb-linux.kernel.vmlinux.h" /************************************************************************* @@ -547,18 +549,29 @@ const int *PackVmlinuxI386::getFilters() const return filters; } -const int *PackVmlinuxARM::getCompressionMethods(int method, int level) const +const int *PackVmlinuxARMEL::getCompressionMethods(int method, int level) const +{ + return Packer::getDefaultCompressionMethods_8(method, level); +} + +const int *PackVmlinuxARMEB::getCompressionMethods(int method, int level) const { return Packer::getDefaultCompressionMethods_8(method, level); } -const int *PackVmlinuxARM::getFilters() const +const int *PackVmlinuxARMEL::getFilters() const { static const int f50[] = { 0x50, FT_END }; return f50; } +const int *PackVmlinuxARMEB::getFilters() const +{ + static const int f51[] = { 0x51, FT_END }; + return f51; +} + // // Examples as of 2004-07-16 [readelf --segments vmlinux # before fiddling]: // @@ -646,18 +659,28 @@ void PackVmlinuxAMD64::buildLoader(const Filter *ft) "LINUX992,IDENTSTR,UPX1HEAD", NULL); } -bool PackVmlinuxARM::is_valid_e_entry(Addr e_entry) +bool PackVmlinuxARMEL::is_valid_e_entry(Addr e_entry) { return 0xc0008000==e_entry; } -Linker* PackVmlinuxARM::newLinker() const +bool PackVmlinuxARMEB::is_valid_e_entry(Addr e_entry) +{ + return 0xc0008000==e_entry; +} + +Linker* PackVmlinuxARMEL::newLinker() const { return new ElfLinkerArmLE; } +Linker* PackVmlinuxARMEB::newLinker() const +{ + return new ElfLinkerArmBE; +} -void PackVmlinuxARM::buildLoader(const Filter *ft) + +void PackVmlinuxARMEL::buildLoader(const Filter *ft) { // prepare loader initLoader(stub_arm_linux_kernel_vmlinux, sizeof(stub_arm_linux_kernel_vmlinux)); @@ -679,6 +702,28 @@ void PackVmlinuxARM::buildLoader(const Filter *ft) addLoader("IDENTSTR,UPX1HEAD", NULL); } +void PackVmlinuxARMEB::buildLoader(const Filter *ft) +{ + // prepare loader + initLoader(stub_armeb_linux_kernel_vmlinux, sizeof(stub_armeb_linux_kernel_vmlinux)); + addLoader("LINUX000", NULL); + if (ft->id) { + assert(ft->calls > 0); + addLoader("LINUX010", NULL); + } + addLoader("LINUX020", NULL); + if (ft->id) { + addFilter32(ft->id); + } + addLoader("LINUX030", NULL); + if (ph.method == M_NRV2E_8) addLoader("NRV2E", NULL); + else if (ph.method == M_NRV2B_8) addLoader("NRV2B", NULL); + else if (ph.method == M_NRV2D_8) addLoader("NRV2D", NULL); + else if (M_IS_LZMA(ph.method)) addLoader("LZMA_ELF00,LZMA_DEC10,LZMA_DEC30", NULL); + else throwBadLoader(); + addLoader("IDENTSTR,UPX1HEAD", NULL); +} + static const #include "stub/i386-linux.kernel.vmlinux-head.h" @@ -686,6 +731,8 @@ static const #include "stub/amd64-linux.kernel.vmlinux-head.h" static const #include "stub/arm-linux.kernel.vmlinux-head.h" +static const +#include "stub/armeb-linux.kernel.vmlinux-head.h" unsigned PackVmlinuxI386::write_vmlinux_head( OutputFile *const fo, @@ -719,7 +766,15 @@ printf("UnCompressed length=0x%x\n", ph.u_len); return sizeof(stub_amd64_linux_kernel_vmlinux_head); } -void PackVmlinuxARM::defineDecompressorSymbols() +void PackVmlinuxARMEL::defineDecompressorSymbols() +{ + super::defineDecompressorSymbols(); + linker->defineSymbol( "COMPRESSED_LENGTH", ph.c_len); + linker->defineSymbol("UNCOMPRESSED_LENGTH", ph.u_len); + linker->defineSymbol("METHOD", ph.method); +} + +void PackVmlinuxARMEB::defineDecompressorSymbols() { super::defineDecompressorSymbols(); linker->defineSymbol( "COMPRESSED_LENGTH", ph.c_len); @@ -744,7 +799,7 @@ void PackVmlinuxAMD64::defineDecompressorSymbols() linker->defineSymbol("PHYSICAL_START", phdri[0].p_paddr); } -unsigned PackVmlinuxARM::write_vmlinux_head( +unsigned PackVmlinuxARMEL::write_vmlinux_head( OutputFile *const fo, Shdr *const stxt ) @@ -766,8 +821,30 @@ unsigned PackVmlinuxARM::write_vmlinux_head( return sizeof(stub_arm_linux_kernel_vmlinux_head); } +unsigned PackVmlinuxARMEB::write_vmlinux_head( + OutputFile *const fo, + Shdr *const stxt +) +{ + // First word from vmlinux-head.S + fo->write(&stub_armeb_linux_kernel_vmlinux_head[0], 4); -bool PackVmlinuxARM::has_valid_vmlinux_head() + // Second word + U32 tmp_u32; + unsigned const t = (0xff000000 & + BeLePolicy::get32(&stub_armeb_linux_kernel_vmlinux_head[4])) + | (0x00ffffff & (0u - 1 + ((3+ ph.c_len)>>2))); + tmp_u32 = t; + fo->write(&tmp_u32, 4); + + stxt->sh_addralign = 4; + stxt->sh_size += sizeof(stub_armeb_linux_kernel_vmlinux_head); + + return sizeof(stub_armeb_linux_kernel_vmlinux_head); +} + + +bool PackVmlinuxARMEL::has_valid_vmlinux_head() { U32 buf[2]; fi->seek(p_text->sh_offset + sizeof(stub_arm_linux_kernel_vmlinux_head) -8, SEEK_SET); @@ -781,6 +858,20 @@ bool PackVmlinuxARM::has_valid_vmlinux_head() return false; } +bool PackVmlinuxARMEB::has_valid_vmlinux_head() +{ + U32 buf[2]; + fi->seek(p_text->sh_offset + sizeof(stub_armeb_linux_kernel_vmlinux_head) -8, SEEK_SET); + fi->readx(buf, sizeof(buf)); + //unsigned const word0 = buf[0]; + unsigned const word1 = buf[1]; + if (0xeb==(word1>>24) + && (0x00ffffff& word1)==(0u - 1 + ((3+ ph.c_len)>>2))) { + return true; + } + return false; +} + bool PackVmlinuxI386::has_valid_vmlinux_head() { unsigned char buf[5]; @@ -1058,6 +1149,7 @@ Linker* PackVmlinuxAMD64::newLinker() const // instantiate instances template class PackVmlinuxBase; +template class PackVmlinuxBase; template class PackVmlinuxBase; diff --git a/src/p_vmlinx.h b/src/p_vmlinx.h index 04ad83b5..0734a45f 100644 --- a/src/p_vmlinx.h +++ b/src/p_vmlinx.h @@ -119,14 +119,14 @@ protected: }; -class PackVmlinuxARM : public PackVmlinuxBase +class PackVmlinuxARMEL : public PackVmlinuxBase { typedef PackVmlinuxBase super; public: - PackVmlinuxARM(InputFile *f) : super(f, Ehdr::EM_ARM, + PackVmlinuxARMEL(InputFile *f) : super(f, Ehdr::EM_ARM, Ehdr::ELFCLASS32, Ehdr::ELFDATA2LSB, "decompress_kernel") { } - virtual int getFormat() const { return UPX_F_VMLINUX_ARM; } - virtual const char *getName() const { return "vmlinux/ARM"; } + virtual int getFormat() const { return UPX_F_VMLINUX_ARMEL; } + virtual const char *getName() const { return "vmlinux/armel"; } virtual const char *getFullName(const options_t *) const { return "arm-linux.kernel.vmlinux"; } virtual const int *getCompressionMethods(int method, int level) const; virtual const int *getFilters() const; @@ -143,6 +143,30 @@ protected: ); }; +class PackVmlinuxARMEB : public PackVmlinuxBase +{ + typedef PackVmlinuxBase super; +public: + PackVmlinuxARMEB(InputFile *f) : super(f, Ehdr::EM_ARM, + Ehdr::ELFCLASS32, Ehdr::ELFDATA2MSB, "decompress_kernel") { } + virtual int getFormat() const { return UPX_F_VMLINUX_ARMEB; } + virtual const char *getName() const { return "vmlinux/armeb"; } + virtual const char *getFullName(const options_t *) const { return "armbe-linux.kernel.vmlinux"; } + virtual const int *getCompressionMethods(int method, int level) const; + virtual const int *getFilters() const; + +protected: + virtual void buildLoader(const Filter *ft); + virtual void defineDecompressorSymbols(); + virtual Linker* newLinker() const; + virtual bool is_valid_e_entry(Addr); + virtual bool has_valid_vmlinux_head(); + virtual unsigned write_vmlinux_head( + OutputFile *const fo, + Shdr *const stxt + ); +}; + class PackVmlinuxAMD64 : public PackVmlinuxBase { diff --git a/src/packer_c.cpp b/src/packer_c.cpp index 437089be..1cd9b5ed 100644 --- a/src/packer_c.cpp +++ b/src/packer_c.cpp @@ -208,11 +208,12 @@ const char *Packer::getDecompressorSections() const if (UPX_F_LINUX_ELF_i386 ==ph.format || UPX_F_LINUX_ELFI_i386 ==ph.format || UPX_F_LINUX_ELF64_AMD ==ph.format - || UPX_F_LINUX_ELF32_ARMLE==ph.format + || UPX_F_LINUX_ELF32_ARMEL==ph.format || UPX_F_LINUX_ELFPPC32 ==ph.format - || UPX_F_LINUX_ELF32_ARMBE==ph.format + || UPX_F_LINUX_ELF32_ARMEB==ph.format || UPX_F_BSD_ELF_i386 ==ph.format - || UPX_F_VMLINUX_ARM ==ph.format + || UPX_F_VMLINUX_ARMEL ==ph.format + || UPX_F_VMLINUX_ARMEB ==ph.format || UPX_F_MACH_PPC32 ==ph.format || UPX_F_MACH_i386 ==ph.format ) { @@ -244,11 +245,12 @@ void Packer::defineDecompressorSymbols() if (UPX_F_LINUX_ELF_i386 ==ph.format || UPX_F_LINUX_ELFI_i386 ==ph.format || UPX_F_LINUX_ELF64_AMD ==ph.format - || UPX_F_LINUX_ELF32_ARMLE==ph.format + || UPX_F_LINUX_ELF32_ARMEL==ph.format || UPX_F_LINUX_ELFPPC32 ==ph.format - || UPX_F_LINUX_ELF32_ARMBE==ph.format + || UPX_F_LINUX_ELF32_ARMEB==ph.format || UPX_F_BSD_ELF_i386 ==ph.format - || UPX_F_VMLINUX_ARM ==ph.format + || UPX_F_VMLINUX_ARMEL ==ph.format + || UPX_F_VMLINUX_ARMEB ==ph.format || UPX_F_MACH_PPC32 ==ph.format || UPX_F_MACH_i386 ==ph.format ) { diff --git a/src/packmast.cpp b/src/packmast.cpp index 9144e14e..efaa1194 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -192,7 +192,9 @@ Packer* PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const optio // // linux kernel // - if ((p = func(new PackVmlinuxARM(f), user)) != NULL) + if ((p = func(new PackVmlinuxARMEL(f), user)) != NULL) + return p; + if ((p = func(new PackVmlinuxARMEB(f), user)) != NULL) return p; if ((p = func(new PackVmlinuxAMD64(f), user)) != NULL) return p; diff --git a/src/stub/Makefile b/src/stub/Makefile index 992286d9..75ea26e2 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -56,6 +56,8 @@ STUBS += arm-linux.kernel.vmlinux.h STUBS += arm-linux.kernel.vmlinux-head.h STUBS += armeb-linux.elf-entry.h STUBS += armeb-linux.elf-fold.h +STUBS += armeb-linux.kernel.vmlinux.h +STUBS += armeb-linux.kernel.vmlinux-head.h STUBS += arm.v4a-wince.pe.h STUBS += arm.v4t-wince.pe.h STUBS += i086-dos16.com.h @@ -336,6 +338,28 @@ arm-linux.kernel.vmlinux-head.h : $(srcdir)/src/$$T.S $(call tc,bin2h) tmp/$T.bin $@ +# /*********************************************************************** +# // armeb-linux.kernel.vmlinux +# // armeb-linux.kernel.vmlinuz +# // armeb-linux.kernel.vmlinux-head +# ************************************************************************/ + +armeb-linux.kernel.vmlinu%.h : tc_list = armeb-linux.kernel default +armeb-linux.kernel.vmlinu%.h : tc_bfdname = elf32-bigarm + +tc.armeb-linux.kernel.gcc = $(tc.arm-linux.elf.gcc) -mbig-endian + +armeb-linux.kernel.vmlinu%.h : $(srcdir)/src/$$T.S + $(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.bin + $(call tc,f-embed_objinfo,tmp/$T.bin) + $(call tc,bin2h-c) tmp/$T.bin $@ + +armeb-linux.kernel.vmlinux-head.h : $(srcdir)/src/$$T.S + $(call tc,gcc) -c -x assembler-with-cpp $< -o tmp/$T.o + $(call tc,objcopy) --output-target binary --only-section .text tmp/$T.o tmp/$T.bin + $(call tc,bin2h) tmp/$T.bin $@ + + # /*********************************************************************** # // armeb-linux.elf # ************************************************************************/