diff --git a/src/conf.h b/src/conf.h index fc1aa792..2b198440 100644 --- a/src/conf.h +++ b/src/conf.h @@ -474,6 +474,8 @@ private: #define UPX_F_VMLINUZ_ARMEL 31 #define UPX_F_MACH_ARMEL 32 +#define UPX_F_DYLIB_i386 33 + #define UPX_F_PLAIN_TEXT 127 #define UPX_F_ATARI_TOS 129 diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 7011cbc9..b450d526 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -50,9 +50,9 @@ static const #include "stub/arm-darwin.macho-fold.h" template -PackMachBase::PackMachBase(InputFile *f, unsigned cputype, unsigned flavor, - unsigned count, unsigned size) : - super(f), my_cputype(cputype), my_thread_flavor(flavor), +PackMachBase::PackMachBase(InputFile *f, unsigned cputype, unsigned filetype, + unsigned flavor, unsigned count, unsigned size) : + super(f), my_cputype(cputype), my_filetype(filetype), my_thread_flavor(flavor), my_thread_state_word_count(count), my_thread_command_size(size), n_segment(0), rawmseg(NULL), msegcmd(NULL) { @@ -207,6 +207,10 @@ void PackMachARMEL::addStubEntrySections(Filter const */*ft*/) addLoader("MACHMAINY,IDENTSTR,+40,MACHMAINZ,FOLDEXEC", NULL); } +void PackDylibI386::addStubEntrySections(Filter const *ft) +{ + super::addStubEntrySections(ft); +} template void PackMachBase::defineSymbols(Filter const *) @@ -286,6 +290,12 @@ PackMachARMEL::buildLoader(const Filter *ft) stub_arm_darwin_macho_fold, sizeof(stub_arm_darwin_macho_fold), ft ); } +void +PackDylibI386::buildLoader(const Filter *ft) +{ + super::buildLoader(ft); +} + template void PackMachBase::patchLoader() { } @@ -364,6 +374,121 @@ void PackMachARMEL::pack4(OutputFile *fo, Filter &ft) // append PackHeader fo->rewrite(&linfo, sizeof(linfo)); } +#undef PAGE_MASK +#undef PAGE_SIZE +#define PAGE_MASK (~0u<<12) +#define PAGE_SIZE -PAGE_MASK + +void PackDylibI386::pack4(OutputFile *fo, Filter &ft) // append PackHeader +{ + unsigned opos = fo->getBytesWritten(); + segcmdo.filesize = opos; + segcmdo.vmsize += opos; + rcmd.init_address = threado.state.eip; + fo->seek(sizeof(mhdro), SEEK_SET); + fo->rewrite(&segcmdo, sizeof(segcmdo)); + fo->seek(sizeof(mhdro) + mhdro.sizeofcmds - sizeof(rcmd), SEEK_SET); + fo->rewrite(&rcmd, sizeof(rcmd)); + fo->rewrite(&linfo, sizeof(linfo)); + + // Append __IMPORT and __LINKEDIT segments, page aligned. + int slide = 0; + unsigned hdrpos = sizeof(mhdro) + sizeof(segcmdo); + Mach_segment_command const *seg = rawmseg; + Mach_segment_command const *const endseg = + (Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg); + for ( ; seg < endseg; seg = (Mach_segment_command const *)( + seg->cmdsize + (char const *)seg ) + ) switch (~Mach_segment_command::LC_REQ_DYLD & seg->cmd) { + default: // unknown if any file offset field must slide + printf("Unrecognized Macho cmd offset=0x%x cmd=0x%x size=0x%x\n", (char *)seg - (char *)rawmseg, (unsigned)seg->cmd, (unsigned)seg->cmdsize); + // fall through + case Mach_segment_command::LC_THREAD: + case Mach_segment_command::LC_UNIXTHREAD: + case Mach_segment_command::LC_LOAD_DYLIB: + case Mach_segment_command::LC_ID_DYLIB: + case Mach_segment_command::LC_LOAD_DYLINKER: + case Mach_segment_command::LC_ROUTINES: + case Mach_segment_command::LC_SEGMENT_64: + case Mach_segment_command::LC_ROUTINES_64: + case Mach_segment_command::LC_UUID: + case Mach_segment_command::LC_RPATH: + case Mach_segment_command::LC_CODE_SIGNATURE: + case Mach_segment_command::LC_REEXPORT_DYLIB: + hdrpos += seg->cmdsize; + break; // contain no file offset fields + case Mach_segment_command::LC_SEGMENT: { + // __IMPORT and __LINKEDIT must be seen by dylinker before decompression. + // All other segments have been combined into new compressed __TEXT. + if (0==strncmp(&seg->segname[0], "__IMPORT", 1+ 8) + || 0==strncmp(&seg->segname[0], "__LINKEDIT", 1+ 10)) { + Mach_segment_command segcmdtmp = *seg; + opos += ~PAGE_MASK & (0u - opos); // advance to PAGE_SIZE boundary + slide = opos - segcmdtmp.fileoff; + segcmdtmp.fileoff = opos; + + fo->seek(hdrpos, SEEK_SET); + fo->rewrite(&segcmdtmp, sizeof(segcmdtmp)); + hdrpos += sizeof(segcmdtmp); + + // Update the sections. + Mach_section_command const *secp = (Mach_section_command const *)(1+ seg); + unsigned const nsects = segcmdtmp.nsects; + Mach_section_command seccmdtmp; + for (unsigned j = 0; j < nsects; ++secp, ++j) { + seccmdtmp = *secp; + seccmdtmp.offset += slide; + if (seccmdtmp.nreloc) { + seccmdtmp.reloff += slide; + } + fo->rewrite(&seccmdtmp, sizeof(seccmdtmp)); + hdrpos += sizeof(seccmdtmp); + } + + fo->seek(opos, SEEK_SET); + fi->seek(seg->fileoff, SEEK_SET); + unsigned const len = seg->filesize; + char data[len]; + fi->readx(data, len); + fo->write(data, len); + opos += len; + } + } break; + case Mach_segment_command::LC_SYMTAB: { + Mach_symtab_command cmd = *(Mach_symtab_command const *)seg; + if (opos < cmd.symoff) { cmd.symoff += slide; } + if (opos < cmd.stroff) { cmd.stroff += slide; } + fo->seek(hdrpos, SEEK_SET); + fo->rewrite(&cmd, sizeof(cmd)); + hdrpos += sizeof(cmd); + } break; + case Mach_segment_command::LC_DYSYMTAB: { + Mach_dysymtab_command cmd = *(Mach_dysymtab_command const *)seg; + if (opos < cmd.tocoff) { cmd.tocoff += slide; } + if (opos < cmd.modtaboff) { cmd.modtaboff += slide; } + if (opos < cmd.nextrefsymoff) { cmd.extrefsymoff += slide; } + if (opos < cmd.indirectsymoff) { cmd.indirectsymoff += slide; } + if (opos < cmd.extreloff) { cmd.extreloff += slide; } + if (opos < cmd.locreloff) { cmd.locreloff += slide; } + fo->seek(hdrpos, SEEK_SET); + fo->rewrite(&cmd, sizeof(cmd)); + hdrpos += sizeof(cmd); + } break; + case Mach_segment_command::LC_SEGMENT_SPLIT_INFO: { + Mach_segsplit_info_command cmd = *(Mach_segsplit_info_command const *)seg; + if (opos < cmd.dataoff) { cmd.dataoff += slide; } + fo->seek(hdrpos, SEEK_SET); + fo->rewrite(&cmd, sizeof(cmd)); + hdrpos += sizeof(cmd); + } break; + } // end 'switch' + fo->seek(opos, SEEK_SET); // BUG: "fo->seek(0, SEEK_END);" is broken + + // offset of p_info in compressed file + overlay_offset = sizeof(mhdro) + mhdro.sizeofcmds + sizeof(linfo); + PackMachBase::pack4(fo, ft); +} + void PackMachPPC32::pack3(OutputFile *fo, Filter &ft) // append loader { BE32 disp; @@ -528,11 +653,6 @@ void PackMachBase::pack2(OutputFile *fo, Filter &ft) // append compressed bo segcmdo.filesize = fo->getBytesWritten(); } -#undef PAGE_MASK -#undef PAGE_SIZE -#define PAGE_MASK (~0u<<12) -#define PAGE_SIZE -PAGE_MASK - void PackMachPPC32::pack1_setup_threado(OutputFile *const fo) { threado.cmd = Mach_segment_command::LC_UNIXTHREAD; @@ -567,16 +687,39 @@ template void PackMachBase::pack1(OutputFile *const fo, Filter &/*ft*/) // generate executable header { mhdro = mhdri; - mhdro.ncmds = 2; - mhdro.sizeofcmds = sizeof(segcmdo) + my_thread_command_size; - mhdro.flags = Mach_header::MH_NOUNDEFS; + if (my_filetype==Mach_header::MH_EXECUTE) { + mhdro.ncmds = 2; + mhdro.sizeofcmds = sizeof(segcmdo) + my_thread_command_size; + mhdro.flags = Mach_header::MH_NOUNDEFS; + } + if (my_filetype==Mach_header::MH_DYLIB) { + mhdro.ncmds += 2; /* new __TEXT, added LC_ROUTINES */ + mhdro.sizeofcmds += sizeof(segcmdo) + sizeof(rcmd); + Mach_segment_command const *seg = rawmseg; + Mach_segment_command const *const endseg = + (Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg); + for (; seg < endseg; seg = (Mach_segment_command const *)( + seg->cmdsize + (char const *)seg)) { + // All except __IMPORT and __LINKEDIT will be coalesced into __TEXT. + if (0!=strncmp(&seg->segname[0], "__IMPORT", 1+ 8) + && 0!=strncmp(&seg->segname[0], "__LINKEDIT", 1+ 10)){ + mhdro.ncmds -= 1; + mhdro.sizeofcmds -= seg->cmdsize; + } + } + } fo->write(&mhdro, sizeof(mhdro)); segcmdo.cmd = Mach_segment_command::LC_SEGMENT; segcmdo.cmdsize = sizeof(segcmdo); strncpy((char *)segcmdo.segname, "__TEXT", sizeof(segcmdo.segname)); - segcmdo.vmaddr = PAGE_MASK & (~PAGE_MASK + - msegcmd[n_segment -1].vmsize + msegcmd[n_segment -1].vmaddr ); + if (my_filetype==Mach_header::MH_EXECUTE) { + segcmdo.vmaddr = PAGE_MASK & (~PAGE_MASK + + msegcmd[n_segment -1].vmsize + msegcmd[n_segment -1].vmaddr ); + } + if (my_filetype==Mach_header::MH_DYLIB) { + segcmdo.vmaddr = 0; + } segcmdo.vmsize = 0; // adjust later segcmdo.fileoff = 0; segcmdo.filesize = 0; // adjust later @@ -588,7 +731,25 @@ void PackMachBase::pack1(OutputFile *const fo, Filter &/*ft*/) // generate e segcmdo.flags = 0; fo->write(&segcmdo, sizeof(segcmdo)); - pack1_setup_threado(fo); + if (my_filetype==Mach_header::MH_EXECUTE) { + pack1_setup_threado(fo); + } + if (my_filetype==Mach_header::MH_DYLIB) { + Mach_segment_command const *seg = rawmseg; + Mach_segment_command const *const endseg = + (Mach_segment_command const *)(mhdri.sizeofcmds + (char const *)seg); + for (; seg < endseg; seg = (Mach_segment_command const *)( + seg->cmdsize + (char const *)seg)) { + if (0==strncmp(&seg->segname[0], "__IMPORT", 1+ 8) + || 0==strncmp(&seg->segname[0], "__LINKEDIT", 1+ 10)){ + fo->write(seg, seg->cmdsize); + } + } + memset(&rcmd, 0, sizeof(rcmd)); + rcmd.cmd= Mach_segment_command::LC_ROUTINES; + rcmd.cmdsize = sizeof(rcmd); + fo->write(&rcmd, sizeof(rcmd)); + } sz_mach_headers = fo->getBytesWritten(); memset((char *)&linfo, 0, sizeof(linfo)); @@ -679,7 +840,7 @@ bool PackMachBase::canPack() if (Mach_header::MH_MAGIC !=mhdri.magic || my_cputype !=mhdri.cputype - || Mach_header::MH_EXECUTE !=mhdri.filetype + || my_filetype !=mhdri.filetype ) return false; @@ -700,12 +861,12 @@ bool PackMachBase::canPack() // Check that LC_SEGMENTs form one contiguous chunk of the file. for (unsigned j= 0; j < mhdri.ncmds; ++j) { if (Mach_segment_command::LC_SEGMENT==msegcmd[j].cmd) { - if (0xfff & (msegcmd[j].fileoff | msegcmd[j].vmaddr)) { + if (~PAGE_MASK & (msegcmd[j].fileoff | msegcmd[j].vmaddr)) { return false; } if (0 < j) { - unsigned const sz = ~0xfff - & (0xfff + msegcmd[j-1].filesize); + unsigned const sz = PAGE_MASK + & (~PAGE_MASK + msegcmd[j-1].filesize); if ((sz + msegcmd[j-1].fileoff)!=msegcmd[j].fileoff) { return false; } diff --git a/src/p_mach.h b/src/p_mach.h index 39146f8a..6f542a92 100644 --- a/src/p_mach.h +++ b/src/p_mach.h @@ -139,6 +139,77 @@ __packed_struct(Mach_section_command) #include "p_mach_enum.h" __packed_struct_end() +template +__packed_struct(Mach_symtab_command) + typedef typename TMachITypes::Word Word; + typedef typename TMachITypes::Off Off; + + Word cmd; /* LC_SYMTAB */ + Word cmdsize; /* sizeof(struct Mach_symtab_command) */ + Off symoff; /* symbol table offset */ + Word nsyms; /* number of symbol table entries */ + Off stroff; /* string table offset */ + Word strsize; /* string table size in bytes */ +__packed_struct_end() + +template +__packed_struct(Mach_dysymtab_command) + typedef typename TMachITypes::Word Word; + typedef typename TMachITypes::Off Off; + + Word cmd; /* LC_DYSYMTAB */ + Word cmdsize; /* sizeof(struct Mach_dysymtab_command) */ + Word ilocalsym; /* index to local symbols */ + Word nlocalsym; /* number of local symbols */ + Word iextdefsym; /* index to externally defined symbols */ + Word nextdefsym; /* number of externally defined symbols */ + Word iundefsym; /* index to undefined symbols */ + Word nundefsym; /* number of undefined symbols */ + Off tocoff; /* file offset to table of contents */ + Word ntoc; /* number of entries in table of contents */ + Off modtaboff; /* file offset to module table */ + Word nmodtab; /* number of module table entries */ + Off extrefsymoff; /* offset to referenced symbol table */ + Word nextrefsymoff; /* number of referenced symbol table entries */ + Off indirectsymoff; /* file offset to the indirect symbol table */ + Word nindirectsyms; /* number of indirect symbol table entries */ + Off extreloff; /* offset to external relocation entries */ + Word nextrel; /* number of external relocation entries */ + Off locreloff; /* offset to local relocation entries */ + Word nlocrel; /* number of local relocation entries */ +__packed_struct_end() + +template +__packed_struct(Mach_segsplit_info_command) + typedef typename TMachITypes::Word Word; + typedef typename TMachITypes::Off Off; + + Word cmd; /* LC_SEGMENT_SPLIT_INFO */ + Word cmdsize; /* sizeof(struct Mach_segsplit_info_command) */ + Off dataoff; + Word datasize; +__packed_struct_end() + +template +__packed_struct(Mach_routines_command) + typedef typename TMachITypes::Word Word; + typedef typename TMachITypes::Addr Addr; + typedef typename TMachITypes::Off Off; + + Word cmd; + Word cmdsize; + Addr init_address; + Word init_module; + Word reserved1; + Word reserved2; + Word reserved3; + Word reserved4; + Word reserved5; + Word reserved6; +#define WANT_MACH_SEGMENT_ENUM 1 +#include "p_mach_enum.h" +__packed_struct_end() + template __packed_struct(Mach_ppc_thread_state) typedef typename TMachITypes::Addr Addr; @@ -221,6 +292,26 @@ __packed_struct(Mach_ppc_thread_state64) Word vrsave; /* Vector Save Register */ __packed_struct_end() +template +__packed_struct(Mach_routines_command_64) + typedef typename TMachITypes::Word Word; + typedef typename TMachITypes::Addr Addr; + typedef typename TMachITypes::Xword Xword; + + Word cmd; + Word cmdsize; + Addr init_address; + Xword init_module; + Xword reserved1; + Xword reserved2; + Xword reserved3; + Xword reserved4; + Xword reserved5; + Xword reserved6; +#define WANT_MACH_SEGMENT_ENUM 1 +#include "p_mach_enum.h" +__packed_struct_end() + } // namespace N_Mach64 namespace N_Mach { @@ -245,6 +336,10 @@ struct MachClass_32 typedef N_Mach::Mach_header Mach_header; typedef N_Mach::Mach_segment_command Mach_segment_command; typedef N_Mach::Mach_section_command Mach_section_command; + typedef N_Mach::Mach_symtab_command Mach_symtab_command; + typedef N_Mach::Mach_dysymtab_command Mach_dysymtab_command; + typedef N_Mach::Mach_segsplit_info_command Mach_segsplit_info_command; + typedef N_Mach::Mach_routines_command Mach_routines_command; typedef N_Mach::Mach_ppc_thread_state Mach_ppc_thread_state; typedef N_Mach::Mach_i386_thread_state Mach_i386_thread_state; typedef N_Mach::Mach_ARM_thread_state Mach_ARM_thread_state; @@ -270,6 +365,10 @@ struct MachClass_64 typedef N_Mach::Mach_header64 Mach_header; typedef N_Mach::Mach_segment_command Mach_segment_command; typedef N_Mach::Mach_section_command Mach_section_command; + typedef N_Mach::Mach_symtab_command Mach_symtab_command; + typedef N_Mach::Mach_dysymtab_command Mach_dysymtab_command; + typedef N_Mach::Mach_segsplit_info_command Mach_segsplit_info_command; + typedef N_Mach::Mach_routines_command Mach_routines_command; static void compileTimeAssertions() { BeLePolicy::compileTimeAssertions(); @@ -288,21 +387,45 @@ typedef N_Mach::MachClass_64 MachClass_LE64; // shortcuts typedef MachClass_Host32::Mach_segment_command Mach32_segment_command; typedef MachClass_Host32::Mach_section_command Mach32_section_command; +typedef MachClass_Host32::Mach_symtab_command Mach32_symtab_command; +typedef MachClass_Host32::Mach_dysymtab_command Mach32_dysymtab_command; +typedef MachClass_Host32::Mach_segsplit_info_command Mach32_segsplit_info_command; +typedef MachClass_Host32::Mach_routines_command Mach32_routines_command; typedef MachClass_Host64::Mach_segment_command Mach64_segment_command; typedef MachClass_Host64::Mach_section_command Mach64_section_command; +typedef MachClass_Host64::Mach_symtab_command Mach64_symtab_command; +typedef MachClass_Host64::Mach_dysymtab_command Mach64_dysymtab_command; +typedef MachClass_Host64::Mach_segsplit_info_command Mach64_segsplit_info_command; +typedef MachClass_Host64::Mach_routines_command Mach64_routines_command; typedef MachClass_BE32::Mach_segment_command MachBE32_segment_command; typedef MachClass_BE32::Mach_section_command MachBE32_section_command; +typedef MachClass_BE32::Mach_symtab_command MachBE32_symtab_command; +typedef MachClass_BE32::Mach_dysymtab_command MachBE32_dysymtab_command; +typedef MachClass_BE32::Mach_segsplit_info_command MachBE32_segsplit_info_command; +typedef MachClass_BE32::Mach_routines_command MachBE32_routines_command; typedef MachClass_BE64::Mach_segment_command MachBE64_segment_command; typedef MachClass_BE64::Mach_section_command MachBE64_section_command; +typedef MachClass_BE64::Mach_symtab_command MachBE64_symtab_command; +typedef MachClass_BE64::Mach_dysymtab_command MachBE64_dysymtab_command; +typedef MachClass_BE64::Mach_segsplit_info_command MachBE64_segsplit_info_command; +typedef MachClass_BE64::Mach_routines_command MachBE64_routines_command; typedef MachClass_LE32::Mach_segment_command MachLE32_segment_command; typedef MachClass_LE32::Mach_section_command MachLE32_section_command; +typedef MachClass_LE32::Mach_symtab_command MachLE32_symtab_command; +typedef MachClass_LE32::Mach_dysymtab_command MachLE32_dysymtab_command; +typedef MachClass_LE32::Mach_segsplit_info_command MachLE32_segsplit_info_command; +typedef MachClass_LE32::Mach_routines_command MachLE32_routines_command; typedef MachClass_LE64::Mach_segment_command MachLE64_segment_command; typedef MachClass_LE64::Mach_section_command MachLE64_section_command; +typedef MachClass_LE64::Mach_symtab_command MachLE64_symtab_command; +typedef MachClass_LE64::Mach_dysymtab_command MachLE64_dysymtab_command; +typedef MachClass_LE64::Mach_segsplit_info_command MachLE64_segsplit_info_command; +typedef MachClass_LE64::Mach_routines_command MachLE64_routines_command; typedef MachClass_BE32::Mach_ppc_thread_state Mach_ppc_thread_state; typedef MachClass_LE32::Mach_i386_thread_state Mach_i386_thread_state; @@ -327,9 +450,14 @@ protected: typedef typename MachClass::Mach_header Mach_header; typedef typename MachClass::Mach_segment_command Mach_segment_command; typedef typename MachClass::Mach_section_command Mach_section_command; + typedef typename MachClass::Mach_symtab_command Mach_symtab_command; + typedef typename MachClass::Mach_dysymtab_command Mach_dysymtab_command; + typedef typename MachClass::Mach_segsplit_info_command Mach_segsplit_info_command; + typedef typename MachClass::Mach_routines_command Mach_routines_command; public: - PackMachBase(InputFile *, unsigned cpuid, unsigned t_flavor, unsigned ts_word_cnt, unsigned tc_size); + PackMachBase(InputFile *, unsigned cpuid, unsigned filetype, + 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; @@ -362,6 +490,7 @@ protected: static int __acc_cdecl_qsort compare_segment_command(void const *aa, void const *bb); unsigned my_cputype; + unsigned my_filetype; unsigned my_thread_flavor; unsigned my_thread_state_word_count; unsigned my_thread_command_size; @@ -375,6 +504,7 @@ protected: Mach_header mhdro; Mach_segment_command segcmdo; + Mach_routines_command rcmd; __packed_struct(b_info) // 12-byte header before each compressed block TE32 sz_unc; // uncompressed_size @@ -419,7 +549,7 @@ class PackMachPPC32 : public PackMachBase public: PackMachPPC32(InputFile *f) : super(f, Mach_header::CPU_TYPE_POWERPC, - Mach_thread_command::PPC_THREAD_STATE, + Mach_header::MH_EXECUTE, Mach_thread_command::PPC_THREAD_STATE, sizeof(Mach_ppc_thread_state)>>2, sizeof(threado)) { } virtual int getFormat() const { return UPX_F_MACH_PPC32; } @@ -454,7 +584,7 @@ class PackMachI386 : public PackMachBase public: PackMachI386(InputFile *f) : super(f, Mach_header::CPU_TYPE_I386, - (unsigned)Mach_thread_command::i386_THREAD_STATE, + Mach_header::MH_EXECUTE, (unsigned)Mach_thread_command::i386_THREAD_STATE, sizeof(Mach_i386_thread_state)>>2, sizeof(threado)) { } virtual int getFormat() const { return UPX_F_MACH_i386; } @@ -483,13 +613,34 @@ protected: Mach_thread_command threado; }; +class PackDylibI386 : public PackMachI386 //PackMachBase +{ + typedef PackMachI386 /*PackMachBase*/ super; + +public: + PackDylibI386(InputFile *f) : super(f) { my_filetype = Mach_header::MH_DYLIB; } + + virtual int getFormat() const { return UPX_F_DYLIB_i386; } + virtual const char *getName() const { return "Dylib/i386"; } + virtual const char *getFullName(const options_t *) const { return "i386-darwin.dylib"; } +protected: + //virtual void pack1_setup_threado(OutputFile *const fo); + //virtual void pack1(OutputFile *, Filter &); // generate executable header + //virtual void pack2(OutputFile *, Filter &); // append compressed data + //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 *); +}; + class PackMachARMEL : public PackMachBase { typedef PackMachBase super; public: PackMachARMEL(InputFile *f) : super(f, Mach_header::CPU_TYPE_ARM, - (unsigned)Mach_thread_command::ARM_THREAD_STATE, + Mach_header::MH_EXECUTE, (unsigned)Mach_thread_command::ARM_THREAD_STATE, sizeof(Mach_ARM_thread_state)>>2, sizeof(threado)) { } virtual int getFormat() const { return UPX_F_MACH_ARMEL; } diff --git a/src/p_mach_enum.h b/src/p_mach_enum.h index 12593d9f..e447d87f 100644 --- a/src/p_mach_enum.h +++ b/src/p_mach_enum.h @@ -50,7 +50,8 @@ CPU_SUBTYPE_ARM_V6 = 6 }; enum { // filetype - MH_EXECUTE = 2 + MH_EXECUTE = 2, + MH_DYLIB = 6 }; enum { // flags MH_NOUNDEFS = 1 @@ -61,10 +62,22 @@ #undef WANT_MACH_SEGMENT_ENUM enum { // cmd LC_SEGMENT = 0x1, + LC_SYMTAB = 0x2, LC_THREAD = 0x4, LC_UNIXTHREAD = 0x5, + LC_DYSYMTAB = 0xb, + LC_LOAD_DYLIB = 0xc, + LC_ID_DYLIB = 0xd, LC_LOAD_DYLINKER = 0xe, - LC_SEGMENT_64 = 0x19 + LC_ROUTINES = 0x11, + LC_SEGMENT_64 = 0x19, + LC_ROUTINES_64 = 0x1a, + LC_UUID = 0x1b, + LC_RPATH = 0x1c, + LC_CODE_SIGNATURE = 0x1d, + LC_SEGMENT_SPLIT_INFO = 0x1e, + LC_REEXPORT_DYLIB = 0x1f, + LC_REQ_DYLD = 0x80000000 // OR'ed ==> must not ignore }; enum { // maxprot VM_PROT_READ = 1, diff --git a/src/packer_c.cpp b/src/packer_c.cpp index 9989e533..e4ccee0d 100644 --- a/src/packer_c.cpp +++ b/src/packer_c.cpp @@ -218,6 +218,7 @@ const char *Packer::getDecompressorSections() const || UPX_F_VMLINUX_PPC32 ==ph.format || UPX_F_MACH_PPC32 ==ph.format || UPX_F_MACH_i386 ==ph.format + || UPX_F_DYLIB_i386 ==ph.format ) { return opt->small ? lzma_elf_small : lzma_elf_fast; } @@ -257,6 +258,7 @@ void Packer::defineDecompressorSymbols() || UPX_F_VMLINUX_PPC32 ==ph.format || UPX_F_MACH_PPC32 ==ph.format || UPX_F_MACH_i386 ==ph.format + || UPX_F_DYLIB_i386 ==ph.format ) { // ELF calls the decompressor many times; the parameters change! return; diff --git a/src/packmast.cpp b/src/packmast.cpp index 741d110c..f69c7241 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -279,6 +279,8 @@ Packer* PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const optio return p; if ((p = func(new PackMachARMEL(f), user)) != NULL) return p; + if ((p = func(new PackDylibI386(f), user)) != NULL) + return p; return NULL; }