mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
use separate stub/armeb-linux.elf-entry and fold
This commit is contained in:
parent
2f483ec8e8
commit
796d58867b
158
src/p_lx_elf.cpp
158
src/p_lx_elf.cpp
|
@ -711,78 +711,27 @@ static const
|
|||
static const
|
||||
#include "stub/arm-linux.elf-fold.h"
|
||||
|
||||
static const
|
||||
#include "stub/armeb-linux.elf-entry.h"
|
||||
static const
|
||||
#include "stub/armeb-linux.elf-fold.h"
|
||||
|
||||
#include "mem.h"
|
||||
|
||||
static void brev(
|
||||
unsigned char *const dst,
|
||||
unsigned char const *const src,
|
||||
unsigned len
|
||||
)
|
||||
{
|
||||
assert(0==(3 & len));
|
||||
// Detect overlap which over-writes src before it is used.
|
||||
assert(!((4+ src)<=dst && dst < (len + src)));
|
||||
for (unsigned j = 0; j < len; j += 4) {
|
||||
// Simple way (and somewhat slow) to allow in-place brev().
|
||||
unsigned char tmp[4];
|
||||
memcpy(tmp, j + src, 4);
|
||||
dst[0+ j] = tmp[3];
|
||||
dst[1+ j] = tmp[2];
|
||||
dst[2+ j] = tmp[1];
|
||||
dst[3+ j] = tmp[0];
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ehdr_bele(Elf_BE32_Ehdr *const ehdr_be, Elf_LE32_Ehdr const *const ehdr_le)
|
||||
{
|
||||
memcpy(&ehdr_be->e_ident, &ehdr_le->e_ident, sizeof(ehdr_be->e_ident));
|
||||
ehdr_be->e_ident[Elf32_Ehdr::EI_DATA] = Elf32_Ehdr::ELFDATA2MSB;
|
||||
ehdr_be->e_type = ehdr_le->e_type;
|
||||
ehdr_be->e_machine = ehdr_le->e_machine;
|
||||
ehdr_be->e_version = ehdr_le->e_version;
|
||||
ehdr_be->e_entry = ehdr_le->e_entry;
|
||||
ehdr_be->e_phoff = ehdr_le->e_phoff;
|
||||
ehdr_be->e_shoff = ehdr_le->e_shoff;
|
||||
ehdr_be->e_flags = ehdr_le->e_flags;
|
||||
ehdr_be->e_ehsize = ehdr_le->e_ehsize;
|
||||
ehdr_be->e_phentsize = ehdr_le->e_phentsize;
|
||||
ehdr_be->e_phnum = ehdr_le->e_phnum;
|
||||
ehdr_be->e_shentsize = ehdr_le->e_shentsize;
|
||||
ehdr_be->e_shnum = ehdr_le->e_shnum;
|
||||
ehdr_be->e_shstrndx = ehdr_le->e_shstrndx;
|
||||
}
|
||||
|
||||
static void
|
||||
ehdr_lebe(Elf_LE32_Ehdr *const ehdr_le, Elf_BE32_Ehdr const *const ehdr_be)
|
||||
{
|
||||
memcpy(&ehdr_le->e_ident, &ehdr_be->e_ident, sizeof(ehdr_le->e_ident));
|
||||
ehdr_le->e_ident[Elf32_Ehdr::EI_DATA] = Elf32_Ehdr::ELFDATA2LSB;
|
||||
ehdr_le->e_type = ehdr_be->e_type;
|
||||
ehdr_le->e_machine = ehdr_be->e_machine;
|
||||
ehdr_le->e_version = ehdr_be->e_version;
|
||||
ehdr_le->e_entry = ehdr_be->e_entry;
|
||||
ehdr_le->e_phoff = ehdr_be->e_phoff;
|
||||
ehdr_le->e_shoff = ehdr_be->e_shoff;
|
||||
ehdr_le->e_flags = ehdr_be->e_flags;
|
||||
ehdr_le->e_ehsize = ehdr_be->e_ehsize;
|
||||
ehdr_le->e_phentsize = ehdr_be->e_phentsize;
|
||||
ehdr_le->e_phnum = ehdr_be->e_phnum;
|
||||
ehdr_le->e_shentsize = ehdr_be->e_shentsize;
|
||||
ehdr_le->e_shnum = ehdr_be->e_shnum;
|
||||
ehdr_le->e_shstrndx = ehdr_be->e_shstrndx;
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf32armBe::buildLoader(Filter const *ft)
|
||||
{
|
||||
ARM_buildLoader(ft, true);
|
||||
buildLinuxLoader(
|
||||
linux_elf32armeb_loader, sizeof(linux_elf32armeb_loader),
|
||||
linux_elf32armeb_fold, sizeof(linux_elf32armeb_fold), ft);
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf32armLe::buildLoader(Filter const *ft)
|
||||
{
|
||||
ARM_buildLoader(ft, false);
|
||||
buildLinuxLoader(
|
||||
linux_elf32arm_loader, sizeof(linux_elf32arm_loader),
|
||||
linux_elf32arm_fold, sizeof(linux_elf32arm_fold), ft);
|
||||
}
|
||||
|
||||
static const
|
||||
|
@ -1222,37 +1171,20 @@ void PackBSDElf32x86::pack1(OutputFile *fo, Filter &ft)
|
|||
generateElfHdr(fo, bsd_i386elf_fold, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
|
||||
}
|
||||
|
||||
void PackLinuxElf32::ARM_pack1(OutputFile *fo, bool const isBE)
|
||||
{
|
||||
Elf32_Ehdr const *const fold = (Elf32_Ehdr const *)&linux_elf32arm_fold;
|
||||
cprElfHdr3 h3;
|
||||
// We need Elf32_Ehdr and Elf32_Phdr with byte gender of target.
|
||||
// The stub may have been compiled differently.
|
||||
if (this->ei_data==fold->e_ident[Elf32_Ehdr::EI_DATA]) {
|
||||
memcpy(&h3, (void const *)linux_elf32arm_fold,
|
||||
sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr) );
|
||||
}
|
||||
else {
|
||||
(isBE ? (void (*)(void *, void const *))ehdr_bele
|
||||
: (void (*)(void *, void const *))ehdr_lebe)
|
||||
((void *)&h3.ehdr, (void const *)linux_elf32arm_fold);
|
||||
brev((unsigned char *)&h3.phdr[0],
|
||||
sizeof(Elf32_Ehdr) + (unsigned char const *)&linux_elf32arm_fold,
|
||||
3*sizeof(Elf32_Phdr) );
|
||||
}
|
||||
generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
|
||||
}
|
||||
|
||||
void PackLinuxElf32armLe::pack1(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
super::pack1(fo, ft);
|
||||
ARM_pack1(fo, false);
|
||||
cprElfHdr3 h3;
|
||||
memcpy(&h3, linux_elf32arm_fold, sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr));
|
||||
generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
|
||||
}
|
||||
|
||||
void PackLinuxElf32armBe::pack1(OutputFile *fo, Filter &ft) // FIXME
|
||||
void PackLinuxElf32armBe::pack1(OutputFile *fo, Filter &ft)
|
||||
{
|
||||
super::pack1(fo, ft);
|
||||
ARM_pack1(fo, true);
|
||||
cprElfHdr3 h3;
|
||||
memcpy(&h3, linux_elf32armeb_fold, sizeof(Elf32_Ehdr) + 2*sizeof(Elf32_Phdr));
|
||||
generateElfHdr(fo, &h3, getbrk(phdri, get_native16(&ehdri.e_phnum)) );
|
||||
}
|
||||
|
||||
void PackLinuxElf32ppc::pack1(OutputFile *fo, Filter &ft)
|
||||
|
@ -1511,60 +1443,6 @@ PackLinuxElf32armLe::getFilters() const
|
|||
return ARM_getFilters(false);
|
||||
}
|
||||
|
||||
void
|
||||
PackLinuxElf32::ARM_buildLoader(const Filter *ft, bool const isBE)
|
||||
{
|
||||
unsigned const sz_loader = sizeof(linux_elf32arm_loader);
|
||||
unsigned const sz_fold = sizeof(linux_elf32arm_fold);
|
||||
|
||||
// Was ARM stub assembled for same endianness as the target?
|
||||
bool const asm_brev = (this->ei_data
|
||||
!= ((Elf32_Ehdr const *)linux_elf32arm_fold)->e_ident[Elf32_Ehdr::EI_DATA] );
|
||||
|
||||
MemBuffer tmp_fold(sz_fold);
|
||||
memcpy(tmp_fold, linux_elf32arm_fold, sz_fold);
|
||||
|
||||
// 0xe3530050 is "cmp fid,#0x50" with fid .req r3
|
||||
if (isBE) { // change filter 0x50 to filter 0x51
|
||||
checkPatch(NULL,0,0,0); // reset
|
||||
if (!asm_brev) { // find 0xe3530050 big-endian
|
||||
patch_be32(tmp_fold, sz_fold, "\xe3\x53\x00\x50", 0xe3530051);
|
||||
}
|
||||
else { // find 0xe3530050 little-endian
|
||||
patch_le32(tmp_fold, sz_fold, "\x50\x00\x53\xe3", 0xe3530051);
|
||||
}
|
||||
checkPatch(NULL,0,0,0); // reset
|
||||
}
|
||||
if (!asm_brev) { // was assembled to match target
|
||||
buildLinuxLoader(linux_elf32arm_loader, sz_loader,
|
||||
tmp_fold, sz_fold, ft );
|
||||
}
|
||||
else { // was assembled brev() from target
|
||||
// linux_elf32arm_loader[] is all instructions, except for two strings
|
||||
// at the end: the copyright message, and the SELinux message.
|
||||
// The copyright message begins and ends with '\n', and the SELinux
|
||||
// message ends with '\n'. So copy back to the third '\n' from the end,
|
||||
// and apply brev() only before that point.
|
||||
MemBuffer brev_loader(sz_loader);
|
||||
int nl = 0;
|
||||
int j;
|
||||
for (j= sz_loader; --j>=0; ) {
|
||||
unsigned char const c = linux_elf32arm_loader[j];
|
||||
brev_loader[j] = c;
|
||||
if ('\n'==c) {
|
||||
if (3==++nl) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
brev(brev_loader, linux_elf32arm_loader, j);
|
||||
(isBE ? (void (*)(void *, void const *))ehdr_bele
|
||||
: (void (*)(void *, void const *))ehdr_lebe)
|
||||
(tmp_fold.getVoidPtr(), (void const *)linux_elf32arm_fold);
|
||||
buildLinuxLoader(brev_loader, sz_loader, tmp_fold, sz_fold, ft);
|
||||
}
|
||||
}
|
||||
|
||||
void PackLinuxElf32::ARM_defineSymbols(Filter const * /*ft*/)
|
||||
{
|
||||
unsigned const hlen = sz_elf_hdrs + sizeof(l_info) + sizeof(p_info);
|
||||
|
|
|
@ -90,10 +90,8 @@ protected:
|
|||
|
||||
// These ARM routines are essentially common to big/little endian,
|
||||
// but the class hierarchy splits after this class.
|
||||
virtual void ARM_buildLoader(Filter const *ft, bool isBE);
|
||||
virtual void ARM_defineSymbols(Filter const *ft);
|
||||
virtual void ARM_updateLoader(OutputFile *);
|
||||
virtual void ARM_pack1(OutputFile *, bool isBE);
|
||||
|
||||
virtual void pack1(OutputFile *, Filter &); // generate executable header
|
||||
virtual void pack2(OutputFile *, Filter &); // append compressed data
|
||||
|
|
|
@ -276,13 +276,13 @@ tc.armeb-linux.elf.gcc = $(tc.arm-linux.elf.gcc) -mbig-endian
|
|||
armeb-linux.elf-entry.h : $(srcdir)/src/$$T.S
|
||||
$(call tc,gcc) -march=armv4 -c $< -o tmp/$T.bin
|
||||
$(call tc,f-embed_objinfo,tmp/$T.bin)
|
||||
$(call tc,bin2h) --ident=linux_elf32arm_loader tmp/$T.bin $@
|
||||
$(call tc,bin2h) --ident=linux_elf32armeb_loader tmp/$T.bin $@
|
||||
|
||||
armeb-linux.elf-fold.h : tmp/$$T.o tmp/armeb-linux.elf-main.o $(srcdir)/src/$$T.lds
|
||||
$(call tc,ld) --strip-all -T $(srcdir)/src/$T.lds -Map tmp/$T.map $(filter %.o,$^) -o tmp/$T.bin
|
||||
$(call tc,f-objstrip,tmp/$T.bin)
|
||||
$(call tc,sstrip) tmp/$T.bin
|
||||
$(call tc,bin2h) --ident=linux_elf32arm_fold tmp/$T.bin $@
|
||||
$(call tc,bin2h) --ident=linux_elf32armeb_fold tmp/$T.bin $@
|
||||
|
||||
tmp/armeb-linux.elf-fold.o : $(srcdir)/src/$$T.S
|
||||
$(call tc,gcc) -c $< -o $@
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
*/
|
||||
|
||||
|
||||
#define LINUX_ELF32ARM_LOADER_SIZE 19529
|
||||
#define LINUX_ELF32ARM_LOADER_ADLER32 0xa7d64535
|
||||
#define LINUX_ELF32ARM_LOADER_CRC32 0x70f522be
|
||||
#define LINUX_ELF32ARMEB_LOADER_SIZE 19529
|
||||
#define LINUX_ELF32ARMEB_LOADER_ADLER32 0xa7d64535
|
||||
#define LINUX_ELF32ARMEB_LOADER_CRC32 0x70f522be
|
||||
|
||||
unsigned char linux_elf32arm_loader[19529] = {
|
||||
unsigned char linux_elf32armeb_loader[19529] = {
|
||||
127, 69, 76, 70, 1, 2, 1, 97, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 0 */
|
||||
0, 1, 0, 40, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 10 */
|
||||
0, 0, 23,244, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 40, /* 0x 20 */
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
*/
|
||||
|
||||
|
||||
#define LINUX_ELF32ARM_FOLD_SIZE 2108
|
||||
#define LINUX_ELF32ARM_FOLD_ADLER32 0x5e5d608f
|
||||
#define LINUX_ELF32ARM_FOLD_CRC32 0xfcfdc28a
|
||||
#define LINUX_ELF32ARMEB_FOLD_SIZE 2108
|
||||
#define LINUX_ELF32ARMEB_FOLD_ADLER32 0x65a66090
|
||||
#define LINUX_ELF32ARMEB_FOLD_CRC32 0xdee2e92e
|
||||
|
||||
unsigned char linux_elf32arm_fold[2108] = {
|
||||
unsigned char linux_elf32armeb_fold[2108] = {
|
||||
127, 69, 76, 70, 1, 2, 1, 97, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x 0 */
|
||||
0, 2, 0, 40, 0, 0, 0, 1, 0, 0,128,128, 0, 0, 0, 52, /* 0x 10 */
|
||||
0, 0, 0, 0, 0, 0, 0, 2, 0, 52, 0, 32, 0, 2, 0, 0, /* 0x 20 */
|
||||
|
@ -47,7 +47,7 @@ unsigned char linux_elf32arm_fold[2108] = {
|
|||
226,143, 96, 36,226,137,144, 12,227,160,176, 0,233, 45, 15,248, /* 0x c0 */
|
||||
232,189, 0, 15,235, 0, 1,132,225,160,224, 0,226,141,208, 20, /* 0x d0 */
|
||||
226,141,220, 10,232,189, 0, 7,229, 18,240, 4,226, 3, 48,255, /* 0x e0 */
|
||||
227, 83, 0, 80, 17,160,240, 14,225,176, 17, 33, 19, 80, 0, 0, /* 0x f0 */
|
||||
227, 83, 0, 81, 17,160,240, 14,225,176, 17, 33, 19, 80, 0, 0, /* 0x f0 */
|
||||
1,160,240, 14,226, 65, 16, 1,231,144, 33, 1,226, 2, 52, 15, /* 0x 100 */
|
||||
227, 83, 4, 11, 26, 0, 0, 4,226, 2, 52,255,224, 66, 32, 1, /* 0x 110 */
|
||||
227,194, 36,255,225,130, 32, 3,231,128, 33, 1,227, 81, 0, 0, /* 0x 120 */
|
||||
|
|
|
@ -92,8 +92,11 @@ f_unfilter: @ (char *ptr, uint len, uint cto, uint fid)
|
|||
t1 .req r2
|
||||
t2 .req r3
|
||||
|
||||
#ifndef FILTER_ID /*{*/
|
||||
#define FILTER_ID 0x50 /* little-endian */
|
||||
#endif /*}*/
|
||||
and fid,fid,#0xff
|
||||
cmp fid,#0x50 @ last use of fid
|
||||
cmp fid,#FILTER_ID @ last use of fid
|
||||
movne pc,lr @ no-op if not filter 0x50
|
||||
|
||||
movs len,len,lsr #2 @ word count
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
@ <jreiser@users.sourceforge.net>
|
||||
@
|
||||
|
||||
|
||||
#define FILTER_ID 0x51 /* big-endian */
|
||||
#include "arm-linux.elf-fold.S"
|
||||
|
||||
#undef FILTER_ID
|
||||
|
||||
@ vi:ts=8:et:nowrap
|
||||
|
|
Loading…
Reference in New Issue
Block a user