1
0
mirror of https://github.com/upx/upx.git synced 2025-08-07 22:46:51 +08:00

PackMachFat

This commit is contained in:
John Reiser
2007-02-05 14:00:41 -08:00
parent a545a3938f
commit f27b399f81
5 changed files with 179 additions and 6 deletions

View File

@ -464,6 +464,7 @@ private:
#define UPX_F_MACH_PPC32 131
#define UPX_F_LINUX_ELFPPC32 132
#define UPX_F_LINUX_ELF32_ARMBE 133
#define UPX_F_MACH_FAT 134
// compression methods

View File

@ -60,6 +60,7 @@ public:
int getFd() const { return _fd; }
const char *getName() const { return _name; }
virtual off_t st_size() const; // { return _length; }
virtual void set_extent(off_t offset, off_t length);
protected:
void sopen();
@ -68,7 +69,6 @@ protected:
virtual void write(const void *buf, int len);
virtual void seek(off_t off, int whence);
virtual off_t tell() const;
virtual void set_extent(off_t offset, off_t length);
int _fd;
int _flags;

View File

@ -618,6 +618,128 @@ bool PackMachBase<T>::canPack()
template class PackMachBase<MachClass_BE32>;
template class PackMachBase<MachClass_LE32>;
PackMachFat::PackMachFat(InputFile *f) : super(f)
{
bele = &N_BELE_RTP::le_policy; // sham
}
PackMachFat::~PackMachFat()
{
}
const int *PackMachFat::getCompressionMethods(int /*method*/, int /*level*/) const
{
static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
return m_nrv2e; // sham
}
const int *PackMachFat::getFilters() const
{
static const int filters[] = { 0x49, FT_END };
return filters; // sham
}
void PackMachFat::pack(OutputFile *fo)
{
fo->write(&fat_head, sizeof(fat_head.fat) +
fat_head.fat.nfat_arch * sizeof(fat_head.arch[0]));
for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) {
unsigned base = fo->getBytesWritten();
base += ~(~0u<<fat_head.arch[j].align) & -base;
fo->seek(base, SEEK_SET);
fo->set_extent(base, ~0u);
fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size);
switch (fat_head.arch[j].cputype) {
case PackMachFat::CPU_TYPE_I386: {
PackMachI386 packer(fi);
packer.initPackHeader();
packer.canPack();
packer.updatePackHeader();
packer.pack(fo);
} break;
case PackMachFat::CPU_TYPE_POWERPC: {
PackMachPPC32 packer(fi);
packer.initPackHeader();
packer.canPack();
packer.updatePackHeader();
packer.pack(fo);
} break;
} // switch cputype
fat_head.arch[j].offset = base;
fat_head.arch[j].size = fo->getBytesWritten() - base;
}
fo->set_extent(0, ~0u);
fo->seek(0, SEEK_SET);
fo->write(&fat_head, sizeof(fat_head.fat) +
fat_head.fat.nfat_arch * sizeof(fat_head.arch[0]));
}
void PackMachFat::unpack(OutputFile */*fo*/)
{
assert(false);
}
bool PackMachFat::canPack()
{
struct Mach_fat_arch *arch = &fat_head.arch[0];
fi->readx(&fat_head, sizeof(fat_head));
if (Mach_fat_header::FAT_MAGIC_SWAB==fat_head.fat.magic) {
unsigned *const p = &fat_head.fat.magic;
for (unsigned j = 0; j < sizeof(fat_head)/sizeof(unsigned); ++j) {
p[j] = acc_swab32(p[j]);
}
}
if (Mach_fat_header::FAT_MAGIC!=fat_head.fat.magic
|| N_FAT_ARCH < fat_head.fat.nfat_arch) {
return false;
}
for (unsigned j=0; j < fat_head.fat.nfat_arch; ++j) {
fi->set_extent(fat_head.arch[j].offset, fat_head.arch[j].size);
switch (arch[j].cputype) {
default: return false;
case PackMachFat::CPU_TYPE_I386: {
PackMachI386 packer(fi);
if (!packer.canPack())
return false;
} break;
case PackMachFat::CPU_TYPE_POWERPC: {
PackMachPPC32 packer(fi);
if (!packer.canPack())
return false;
} break;
} // switch cputype
}
return true;
}
int PackMachFat::canUnpack()
{
return 0;
}
void PackMachFat::buildLoader(const Filter */*ft*/)
{
assert(false);
}
Linker* PackMachFat::newLinker() const
{
return new ElfLinkerX86; // sham
}
void PackMachFat::list()
{
assert(false);
}
void PackMachFat::fileInfo()
{
assert(false);
}
/*
vi:ts=4:et
*/

View File

@ -33,8 +33,9 @@
// of the machine on which they were created. We must deal with both kinds.
struct Mach_fat_header {
unsigned magic;
enum e8 {
FAT_MAGIC = 0xcafebabe
enum e8 { // note conflict with java bytecode PackLinuxI386
FAT_MAGIC = 0xcafebabe,
FAT_MAGIC_SWAB = 0xbebafeca,
};
unsigned nfat_arch; // Number of Mach_fat_arch which follow.
};
@ -214,7 +215,7 @@ struct Mach_ppc_thread_state64
Xword r16,r17,r18,r19,r20,r21,r22,r23;
Xword r24,r25,r26,r27,r28,r29,r30,r31;
Word cr; /* Condition register */
Word cr; /* Condition register */ // FIXME: Xword?
Xword xer; /* User's integer exception register */
Xword lr; /* Link register */
Xword ctr; /* Count register */
@ -236,7 +237,7 @@ struct MachClass_32
typedef typename TP::U16 U16;
typedef typename TP::U32 U32;
typedef typename TP::U64 U64;
typedef N_Mach::MachITypes<U32, U32, U32, U32> MachITypes;
typedef N_Mach::MachITypes<U32, U64, U32, U32> MachITypes;
typedef typename MachITypes::Addr Addr;
// Mach types
@ -454,6 +455,53 @@ protected:
__attribute_packed;
};
class PackMachFat : public Packer
{
typedef Packer super;
public:
PackMachFat(InputFile *f);
virtual ~PackMachFat();
virtual int getVersion() const { return 13; }
virtual int getFormat() const { return UPX_F_MACH_FAT; }
virtual const char *getName() const { return "Mach/fat"; }
virtual const char *getFullName(const options_t *) const { return "fat-darwin.macho"; }
virtual const int *getCompressionMethods(int method, int level) const;
virtual const int *getFilters() const;
protected:
// implementation
virtual void pack(OutputFile *fo);
virtual void unpack(OutputFile *fo);
virtual void list();
virtual void fileInfo();
public:
virtual bool canPack();
virtual int canUnpack();
protected:
// loader core
virtual void buildLoader(const Filter *ft);
virtual Linker* newLinker() const;
protected:
enum { N_FAT_ARCH = 5 };
struct Fat_head {
struct Mach_fat_header fat;
struct Mach_fat_arch arch[N_FAT_ARCH];
} fat_head;
// UI handler
UiPacker *uip;
// linker
Linker *linker;
#define WANT_MACH_HEADER_ENUM
#include "p_mach_enum.h"
#undef WANT_MACH_HEADER_ENUM
};
#endif /* already included */

View File

@ -244,7 +244,9 @@ Packer* PackMaster::visitAllPackers(visit_func_t func, InputFile *f, const optio
}
if ((p = func(new PackBSDI386(f), user)) != NULL)
return p;
if ((p = func(new PackLinuxI386(f), user)) != NULL)
if ((p = func(new PackMachFat(f), user)) != NULL) // cafebabe conflict
return p;
if ((p = func(new PackLinuxI386(f), user)) != NULL) // cafebabe conflict
return p;
//