PackMachPPC32

This commit is contained in:
John Reiser
2007-02-03 11:04:57 -08:00
parent 2132a28a17
commit 99be1e798b
3 changed files with 157 additions and 19 deletions
+138 -14
View File
@@ -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 <class T>
PackMachBase<T>::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<T>::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<BeLePolicy>();
}
template <class T>
@@ -55,7 +62,8 @@ PackMachBase<T>::~PackMachBase()
delete [] rawmseg;
}
const int *PackMachPPC32::getCompressionMethods(int /*method*/, int /*level*/) const
template <class T>
const int *PackMachBase<T>::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 <class T>
void
PackMachBase<T>::addStubEntrySections(Filter const *)
@@ -89,6 +108,68 @@ PackMachBase<T>::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 <class T>
void PackMachBase<T>::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 <class T>
void PackMachBase<T>::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<T>::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<T>::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<T>::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 <class T>
void PackMachBase<T>::pack1(OutputFile *const fo, Filter &/*ft*/) // generate executable header
{
@@ -433,8 +558,7 @@ void PackMachBase<T>::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<T>::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;