From 99be1e798b70a2df7fd48dd6f3053e7947ccd8ac Mon Sep 17 00:00:00 2001 From: John Reiser Date: Sat, 3 Feb 2007 11:04:57 -0800 Subject: [PATCH] PackMachPPC32 --- src/p_mach.cpp | 152 ++++++++++++++++++++++++++++++++++++++++++----- src/p_mach.h | 22 +++++-- src/packmast.cpp | 2 + 3 files changed, 157 insertions(+), 19 deletions(-) diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 4b871315..8a78d6aa 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -39,13 +39,20 @@ static const static const #include "stub/powerpc-darwin.macho-fold.h" +static const +#include "stub/i386-darwin.macho-entry.h" +static const +#include "stub/i386-darwin.macho-fold.h" + template -PackMachBase::PackMachBase(InputFile *f, unsigned flavor, unsigned count, - unsigned size) : - super(f), my_thread_flavor(flavor), my_thread_state_word_count(count), - my_thread_command_size(size), +PackMachBase::PackMachBase(InputFile *f, unsigned cputype, unsigned flavor, + unsigned count, unsigned size) : + super(f), my_cputype(cputype), my_thread_flavor(flavor), + my_thread_state_word_count(count), my_thread_command_size(size), n_segment(0), rawmseg(0), msegcmd(0) { + MachClass::compileTimeAssertions(); + bele = N_BELE_CTP::getRTP(); } template @@ -55,7 +62,8 @@ PackMachBase::~PackMachBase() delete [] rawmseg; } -const int *PackMachPPC32::getCompressionMethods(int /*method*/, int /*level*/) const +template +const int *PackMachBase::getCompressionMethods(int /*method*/, int /*level*/) const { // There really is no LE bias in M_NRV2E_LE32. static const int m_nrv2e[] = { M_NRV2E_LE32, M_END }; @@ -69,11 +77,22 @@ const int *PackMachPPC32::getFilters() const return filters; } +int const *PackMachI386::getFilters() const +{ + static const int filters[] = { 0x49, FT_END }; + return filters; +} + Linker *PackMachPPC32::newLinker() const { return new ElfLinkerPpc32; } +Linker *PackMachI386::newLinker() const +{ + return new ElfLinkerX86; +} + template void PackMachBase::addStubEntrySections(Filter const *) @@ -89,6 +108,68 @@ PackMachBase::addStubEntrySections(Filter const *) addLoader("ELFMAINY,IDENTSTR,+40,ELFMAINZ,FOLDEXEC", NULL); } +void PackMachI386::addStubEntrySections(Filter const *ft) +{ + int const n_mru = ft->n_mru; // FIXME: belongs to filter? packerf? + + // entry to stub + addLoader("LEXEC000", NULL); + + if (ft->id) { + { // decompr, unfilter are separate + addLoader("LXUNF000", NULL); + addLoader("LXUNF002", NULL); + if (0x80==(ft->id & 0xF0)) { + if (256==n_mru) { + addLoader("MRUBYTE0", NULL); + } + else if (n_mru) { + addLoader("LXMRU005", NULL); + } + if (n_mru) { + addLoader("LXMRU006", NULL); + } + else { + addLoader("LXMRU007", NULL); + } + } + else if (0x40==(ft->id & 0xF0)) { + addLoader("LXUNF008", NULL); + } + addLoader("LXUNF010", NULL); + } + if (n_mru) { + addLoader("LEXEC009", NULL); + } + } + addLoader("LEXEC010", NULL); + addLoader(getDecompressorSections(), NULL); + addLoader("LEXEC015", NULL); + if (ft->id) { + { // decompr, unfilter are separate + if (0x80!=(ft->id & 0xF0)) { + addLoader("LXUNF042", NULL); + } + } + addFilter32(ft->id); + { // decompr, unfilter are separate + if (0x80==(ft->id & 0xF0)) { + if (0==n_mru) { + addLoader("LXMRU058", NULL); + } + } + addLoader("LXUNF035", NULL); + } + } + else { + addLoader("LEXEC017", NULL); + } + + addLoader("IDENTSTR", NULL); + addLoader("LEXEC020", NULL); + addLoader("FOLDEXEC", NULL); +} + template void PackMachBase::defineSymbols(Filter const *) @@ -151,6 +232,14 @@ PackMachPPC32::buildLoader(const Filter *ft) stub_powerpc_darwin_macho_fold, sizeof(stub_powerpc_darwin_macho_fold), ft ); } +void +PackMachI386::buildLoader(const Filter *ft) +{ + buildMachLoader( + stub_i386_darwin_macho_entry, sizeof(stub_i386_darwin_macho_entry), + stub_i386_darwin_macho_fold, sizeof(stub_i386_darwin_macho_fold), ft ); +} + template void PackMachBase::patchLoader() { } @@ -201,6 +290,20 @@ void PackMachPPC32::pack4(OutputFile *fo, Filter &ft) // append PackHeader fo->write(&linfo, sizeof(linfo)); } +void PackMachI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader +{ + // offset of p_info in compressed file + overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo); + + super::pack4(fo, ft); + segcmdo.filesize = fo->getBytesWritten(); + segcmdo.vmsize += segcmdo.filesize; + fo->seek(sizeof(mhdro), SEEK_SET); + fo->write(&segcmdo, sizeof(segcmdo)); + fo->write(&threado, sizeof(threado)); + fo->write(&linfo, sizeof(linfo)); +} + void PackMachPPC32::pack3(OutputFile *fo, Filter &ft) // append loader { BE32 disp; @@ -208,13 +311,27 @@ void PackMachPPC32::pack3(OutputFile *fo, Filter &ft) // append loader unsigned len = fo->getBytesWritten(); fo->write(&zero, 3& (0u-len)); len += (3& (0u-len)) + sizeof(disp); - set_be32(&disp, 4+ len - sz_mach_headers); // 4: sizeof(instruction) + disp = 4+ len - sz_mach_headers; // 4: sizeof(instruction) fo->write(&disp, sizeof(disp)); threado.state.srr0 = len + segcmdo.vmaddr; /* entry address */ super::pack3(fo, ft); } +void PackMachI386::pack3(OutputFile *fo, Filter &ft) // append loader +{ + LE32 disp; + unsigned const zero = 0; + unsigned len = fo->getBytesWritten(); + fo->write(&zero, 3& (0u-len)); + len += (3& (0u-len)) + sizeof(disp); + disp = 4+ len - sz_mach_headers; // 4: sizeof(instruction) + fo->write(&disp, sizeof(disp)); + + threado.state.eip = len + segcmdo.vmaddr; /* entry address */ + super::pack3(fo, ft); +} + // Determine length of gap between PT_LOAD phdri[k] and closest PT_LOAD // which follows in the file (or end-of-file). Optimize for common case // where the PT_LOAD are adjacent ascending by .p_offset. Assume no overlap. @@ -228,8 +345,7 @@ unsigned PackMachBase::find_SEGMENT_gap( || 0==msegcmd[k].filesize ) { return 0; } - unsigned const hi = get_native32(&msegcmd[k].fileoff) + - get_native32(&msegcmd[k].filesize); + unsigned const hi = msegcmd[k].fileoff + msegcmd[k].filesize; unsigned lo = ph.u_file_size; unsigned j = k; for (;;) { // circular search, optimize for adjacent ascending @@ -242,7 +358,7 @@ unsigned PackMachBase::find_SEGMENT_gap( } if (Mach_segment_command::LC_SEGMENT==msegcmd[j].cmd && 0!=msegcmd[j].filesize ) { - unsigned const t = get_native32(&msegcmd[j].fileoff); + unsigned const t = msegcmd[j].fileoff; if ((t - hi) < (lo - hi)) { lo = t; if (hi==lo) { @@ -313,8 +429,7 @@ void PackMachBase::pack2(OutputFile *fo, Filter &ft) // append compressed bo for (k = 0; k < n_segment; ++k) { x.size = find_SEGMENT_gap(k); if (x.size) { - x.offset = get_native32(&msegcmd[k].fileoff) + - get_native32(&msegcmd[k].filesize); + x.offset = msegcmd[k].fileoff +msegcmd[k].filesize; packExtent(x, total_in, total_out, 0, fo); } } @@ -339,6 +454,16 @@ void PackMachPPC32::pack1_setup_threado(OutputFile *const fo) fo->write(&threado, sizeof(threado)); } +void PackMachI386::pack1_setup_threado(OutputFile *const fo) +{ + threado.cmd = Mach_segment_command::LC_UNIXTHREAD; + threado.cmdsize = sizeof(threado); + threado.flavor = my_thread_flavor; + threado.count = my_thread_state_word_count; + memset(&threado.state, 0, sizeof(threado.state)); + fo->write(&threado, sizeof(threado)); +} + template void PackMachBase::pack1(OutputFile *const fo, Filter &/*ft*/) // generate executable header { @@ -433,8 +558,7 @@ void PackMachBase::unpack(OutputFile *fo) for (unsigned j = 0; j < ncmds; ++j) { unsigned const size = find_SEGMENT_gap(j); if (size) { - unsigned const where = get_native32(&msegcmd[k].fileoff) + - get_native32(&msegcmd[k].filesize); + unsigned const where = msegcmd[k].fileoff +msegcmd[k].filesize; if (fo) fo->seek(where, SEEK_SET); unpackExtent(size, fo, total_in, total_out, @@ -451,7 +575,7 @@ bool PackMachBase::canPack() fi->readx(&mhdri, sizeof(mhdri)); if (Mach_header::MH_MAGIC !=mhdri.magic - || Mach_header::CPU_TYPE_POWERPC !=mhdri.cputype + || my_cputype !=mhdri.cputype || Mach_header::MH_EXECUTE !=mhdri.filetype ) return false; diff --git a/src/p_mach.h b/src/p_mach.h index 6f116105..a2e7a1ae 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -245,6 +245,10 @@ struct MachClass_32 typedef N_Mach::Mach_section_command Mach_section_command; typedef N_Mach::Mach_ppc_thread_state Mach_ppc_thread_state; typedef N_Mach::Mach_i386_thread_state Mach_i386_thread_state; + + static void compileTimeAssertions() { + BeLePolicy::compileTimeAssertions(); + } }; template @@ -316,9 +320,10 @@ protected: typedef typename MachClass::Mach_section_command Mach_section_command; public: - PackMachBase(InputFile *, unsigned t_flavor, unsigned ts_word_cnt, unsigned tc_size); + PackMachBase(InputFile *, unsigned cpuid, unsigned t_flavor, unsigned ts_word_cnt, unsigned tc_size); virtual ~PackMachBase(); virtual int getVersion() const { return 13; } + virtual const int *getCompressionMethods(int method, int level) const; // called by the generic pack() virtual void pack1(OutputFile *, Filter &); // generate executable header @@ -347,6 +352,7 @@ protected: static int __acc_cdecl_qsort compare_segment_command(void const *aa, void const *bb); + unsigned my_cputype; unsigned my_thread_flavor; unsigned my_thread_state_word_count; unsigned my_thread_command_size; @@ -369,7 +375,7 @@ class PackMachPPC32 : public PackMachBase typedef PackMachBase super; public: - PackMachPPC32::PackMachPPC32(InputFile *f) : super(f, + PackMachPPC32::PackMachPPC32(InputFile *f) : super(f, Mach_header::CPU_TYPE_POWERPC, Mach_thread_command::PPC_THREAD_STATE, sizeof(Mach_ppc_thread_state)>>2, sizeof(threado)) { } @@ -385,7 +391,6 @@ public: virtual void set_native16(void *b, unsigned v) const { set_be16(b, v); } protected: - virtual const int *getCompressionMethods(int method, int level) const; virtual const int *getFilters() const; virtual void pack1_setup_threado(OutputFile *const fo); @@ -412,7 +417,7 @@ class PackMachI386 : public PackMachBase typedef PackMachBase super; public: - PackMachI386(InputFile *f) : super(f, + PackMachI386(InputFile *f) : super(f, Mach_header::CPU_TYPE_I386, (unsigned)Mach_thread_command::i386_THREAD_STATE, sizeof(Mach_i386_thread_state)>>2, sizeof(threado)) { } @@ -420,14 +425,21 @@ public: virtual const char *getName() const { return "Mach/i386"; } virtual const char *getFullName(const options_t *) const { return "i386-darwin.macho"; } protected: - virtual const int *getCompressionMethods(int method, int level) const; virtual const int *getFilters() const; + virtual acc_uint64l_t get_native64(const void *b) const { return get_be64(b); } + virtual unsigned get_native32(const void *b) const { return get_be32(b); } + virtual unsigned get_native16(const void *b) const { return get_be16(b); } + virtual void set_native64(void *b, acc_uint64l_t v) const { set_be64(b, v); } + virtual void set_native32(void *b, unsigned v) const { set_be32(b, v); } + virtual void set_native16(void *b, unsigned v) const { set_be16(b, v); } + virtual void pack1_setup_threado(OutputFile *const fo); virtual void pack3(OutputFile *, Filter &); // append loader virtual void pack4(OutputFile *, Filter &); // append PackHeader virtual Linker* newLinker() const; virtual void buildLoader(const Filter *ft); + virtual void addStubEntrySections(Filter const *); struct Mach_thread_command { diff --git a/src/packmast.cpp b/src/packmast.cpp index 400ec465..58341558 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -264,6 +264,8 @@ Packer* PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const optio // Mach (MacOS X PowerPC) if ((p = func(new PackMachPPC32(f), user)) != NULL) return p; + if ((p = func(new PackMachI386(f), user)) != NULL) + return p; return NULL; }