From 796d58867b031687c1ea01abee0c393954db9149 Mon Sep 17 00:00:00 2001 From: John Reiser Date: Mon, 20 Nov 2006 08:02:28 -0800 Subject: [PATCH] use separate stub/armeb-linux.elf-entry and fold --- src/p_lx_elf.cpp | 158 ++++------------------------ src/p_lx_elf.h | 2 - src/stub/Makefile | 4 +- src/stub/armeb-linux.elf-entry.h | 8 +- src/stub/armeb-linux.elf-fold.h | 10 +- src/stub/src/arm-linux.elf-fold.S | 5 +- src/stub/src/armeb-linux.elf-fold.S | 4 +- 7 files changed, 35 insertions(+), 156 deletions(-) diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index b3bb176d..7f8206eb 100644 --- a/src/p_lx_elf.cpp +++ b/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); diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index bab2b8ee..5b2f1a3e 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -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 diff --git a/src/stub/Makefile b/src/stub/Makefile index de732252..5ef7c37b 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -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 $@ diff --git a/src/stub/armeb-linux.elf-entry.h b/src/stub/armeb-linux.elf-entry.h index feefd755..dd236dd1 100644 --- a/src/stub/armeb-linux.elf-entry.h +++ b/src/stub/armeb-linux.elf-entry.h @@ -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 */ diff --git a/src/stub/armeb-linux.elf-fold.h b/src/stub/armeb-linux.elf-fold.h index ab218050..e8ef2e33 100644 --- a/src/stub/armeb-linux.elf-fold.h +++ b/src/stub/armeb-linux.elf-fold.h @@ -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 */ diff --git a/src/stub/src/arm-linux.elf-fold.S b/src/stub/src/arm-linux.elf-fold.S index 979e9211..e98e0915 100644 --- a/src/stub/src/arm-linux.elf-fold.S +++ b/src/stub/src/arm-linux.elf-fold.S @@ -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 diff --git a/src/stub/src/armeb-linux.elf-fold.S b/src/stub/src/armeb-linux.elf-fold.S index 0e25c119..f152c229 100644 --- a/src/stub/src/armeb-linux.elf-fold.S +++ b/src/stub/src/armeb-linux.elf-fold.S @@ -27,8 +27,8 @@ @ @ - +#define FILTER_ID 0x51 /* big-endian */ #include "arm-linux.elf-fold.S" - +#undef FILTER_ID @ vi:ts=8:et:nowrap