update to ida 7.6, add builds
This commit is contained in:
144
idasdk76/ldr/pilot/common.cpp
Normal file
144
idasdk76/ldr/pilot/common.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static void swap_prc(DatabaseHdrType &h)
|
||||
{
|
||||
h.attributes = swap16(h.attributes);
|
||||
h.version = swap16(h.version);
|
||||
h.creationDate = swap32(h.creationDate);
|
||||
h.modificationDate = swap32(h.modificationDate);
|
||||
h.lastBackupDate = swap32(h.lastBackupDate);
|
||||
h.modificationNumber = swap32(h.modificationNumber);
|
||||
h.appInfoID = swap32(h.appInfoID);
|
||||
h.sortInfoID = swap32(h.sortInfoID);
|
||||
// h.type = swap32(h.type);
|
||||
// h.id = swap32(h.id);
|
||||
h.uniqueIDSeed = swap32(h.uniqueIDSeed);
|
||||
h.nextRecordListID = swap32(h.nextRecordListID);
|
||||
h.numRecords = swap16(h.numRecords);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static void swap_resource_map_entry(ResourceMapEntry &re)
|
||||
{
|
||||
re.id = swap16(re.id);
|
||||
re.ulOffset = swap32(re.ulOffset);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void swap_bitmap(pilot_bitmap_t *b)
|
||||
{
|
||||
b->cx = swap16(b->cx);
|
||||
b->cy = swap16(b->cy);
|
||||
b->cbRow = swap16(b->cbRow);
|
||||
b->ausUnk[0] = swap16(b->ausUnk[0]);
|
||||
b->ausUnk[1] = swap16(b->ausUnk[1]);
|
||||
b->ausUnk[2] = swap16(b->ausUnk[2]);
|
||||
b->ausUnk[3] = swap16(b->ausUnk[3]);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void swap_code0000(code0000_t *cp)
|
||||
{
|
||||
cp->nBytesAboveA5 = swap32(cp->nBytesAboveA5);
|
||||
cp->nBytesBelowA5 = swap32(cp->nBytesBelowA5);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void swap_pref0000(pref0000_t *pp)
|
||||
{
|
||||
pp->flags = swap16(pp->flags);
|
||||
pp->stack_size = swap32(pp->stack_size);
|
||||
pp->heap_size = swap32(pp->heap_size);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Since the Palm Pilot programs are really poorly recognized by usual
|
||||
// methods, we are forced to read the resource tablee to determine
|
||||
// if everying is ok
|
||||
// return 0 if not a PRC, 2 if has ARM code segments, 1 otherwise
|
||||
int is_prc_file(linput_t *li)
|
||||
{
|
||||
DatabaseHdrType h;
|
||||
if ( qlread(li,&h,sizeof(h)) != sizeof(h) )
|
||||
return 0;
|
||||
swap_prc(h);
|
||||
if ( (h.attributes & dmHdrAttrResDB) == 0 )
|
||||
return 0;
|
||||
if ( short(h.numRecords) <= 0 )
|
||||
return 0;
|
||||
const uint64 filesize = qlsize(li);
|
||||
const uint64 lowestpos = uint64(h.numRecords)*sizeof(ResourceMapEntry) + sizeof(h);
|
||||
if ( lowestpos > filesize )
|
||||
return 0;
|
||||
|
||||
// the dates can be plain wrong, so don't check them:
|
||||
// uint32 now = time(NULL);
|
||||
// && uint32(h.lastBackupDate) <= now // use unsigned comparition!
|
||||
// && uint32(h.creationDate) <= now // use unsigned comparition!
|
||||
// && uint32(h.modificationDate) <= now // use unsigned comparition!
|
||||
|
||||
qvector<ResourceMapEntry> re;
|
||||
re.resize(h.numRecords);
|
||||
size_t size = sizeof(ResourceMapEntry) * h.numRecords;
|
||||
if ( qlread(li, re.begin(), size) != size )
|
||||
return 0;
|
||||
|
||||
bool hasArmCode = false;
|
||||
for ( int i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
swap_resource_map_entry(re[i]);
|
||||
if ( re[i].ulOffset >= filesize || re[i].ulOffset < lowestpos )
|
||||
return 0;
|
||||
if ( re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL )
|
||||
hasArmCode = true;
|
||||
}
|
||||
return hasArmCode ? 2 : 1;
|
||||
}
|
||||
|
||||
bool isKnownResource(uint32 resId)
|
||||
{
|
||||
switch ( resId )
|
||||
{
|
||||
case MC4('t', 'F', 'R', 'M'):
|
||||
case MC4('t', 'B', 'T', 'N'):
|
||||
case MC4('t', 'C', 'B', 'X'):
|
||||
case MC4('t', 'F', 'B', 'M'):
|
||||
case MC4('t', 'F', 'L', 'D'):
|
||||
case MC4('t', 'g', 'b', 'n'):
|
||||
case MC4('t', 'G', 'D', 'T'):
|
||||
case MC4('t', 'g', 'p', 'b'):
|
||||
case MC4('t', 'g', 'r', 'b'):
|
||||
case MC4('t', 'G', 'S', 'I'):
|
||||
case MC4('t', 'L', 'B', 'L'):
|
||||
case MC4('t', 'L', 'S', 'T'):
|
||||
case MC4('t', 'P', 'B', 'N'):
|
||||
case MC4('t', 'P', 'U', 'L'):
|
||||
case MC4('t', 'P', 'U', 'T'):
|
||||
case MC4('t', 'R', 'E', 'P'):
|
||||
case MC4('t', 'S', 'C', 'L'):
|
||||
case MC4('t', 's', 'l', 'd'):
|
||||
case MC4('t', 's', 'l', 'f'):
|
||||
case MC4('t', 'S', 'L', 'T'):
|
||||
case MC4('t', 'T', 'B', 'L'):
|
||||
case MC4('T', 'a', 'l', 't'):
|
||||
case MC4('M', 'B', 'A', 'R'):
|
||||
case MC4('M', 'E', 'N', 'U'):
|
||||
case MC4('t', 'S', 'T', 'R'):
|
||||
case MC4('t', 'S', 'T', 'L'):
|
||||
case MC4('T', 'b', 'm', 'p'):
|
||||
case MC4('t', 'b', 'm', 'f'):
|
||||
case MC4('P', 'I', 'C', 'T'):
|
||||
case MC4('t', 'v', 'e', 'r'):
|
||||
case MC4('t', 'A', 'I', 'N'):
|
||||
case MC4('t', 'a', 'i', 'c'):
|
||||
case MC4('t', 'A', 'I', 'S'):
|
||||
case MC4('t', 'A', 'I', 'B'):
|
||||
case MC4('t', 'a', 'i', 'f'):
|
||||
case MC4('I', 'C', 'O', 'N'):
|
||||
case MC4('c', 'i', 'c', 'n'):
|
||||
case MC4('p', 'r', 'e', 'f'):
|
||||
case MC4('x', 'p', 'r', 'f'):
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
14
idasdk76/ldr/pilot/makefile
Normal file
14
idasdk76/ldr/pilot/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=pilot
|
||||
IDCS=pilot.idc
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)pilot$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)expr.hpp \
|
||||
$(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \
|
||||
$(I)xref.hpp ../idaldr.h common.cpp pilot.cpp pilot.hpp
|
||||
912
idasdk76/ldr/pilot/pilot.cpp
Normal file
912
idasdk76/ldr/pilot/pilot.cpp
Normal file
@@ -0,0 +1,912 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include <expr.hpp>
|
||||
#include "pilot.hpp"
|
||||
|
||||
#include "common.cpp"
|
||||
//------------------------------------------------------------------------
|
||||
static void describe_all(DatabaseHdrType &h)
|
||||
{
|
||||
create_filename_cmt();
|
||||
add_pgm_cmt("Version : %04X",h.version);
|
||||
add_pgm_cmt("DatabaseType: %4.4s",(char*)&h.type);
|
||||
add_pgm_cmt("\n appl \"%s\", '%4.4s'", h.name, (char*)&h.id);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Structure of the DATA 0 resource:
|
||||
//
|
||||
// +--------------------------------------------+
|
||||
// | long: offset of CODE 1 xrefs? |- -+
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: Initialized near data (below A5) | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: Uninitialized near data (below A5) | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: Initialized far data (above A5) | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: DATA 0 xrefs | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: CODE 1 xrefs |<--+
|
||||
// +--------------------------------------------+
|
||||
//
|
||||
|
||||
static uchar *apply_relocs(uchar *packed, size_t &packlen, ea_t relocbase, ea_t targetbase, bool code=false)
|
||||
{
|
||||
if ( packlen < 4 )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return NULL;
|
||||
}
|
||||
uint32 nrelocs = swap32(*(uint32*)packed);
|
||||
packed += 4;
|
||||
packlen -= 4;
|
||||
ea_t offset = relocbase;
|
||||
fixup_data_t fd(FIXUP_OFF32);
|
||||
if ( code )
|
||||
fd.set_sel(getseg(targetbase));
|
||||
//msg("%d relocations\n", nrelocs);
|
||||
for ( uint i=0; i < nrelocs; i++ )
|
||||
{
|
||||
if ( packlen < 1 )
|
||||
goto BADDATA;
|
||||
uchar c = *packed;
|
||||
if ( c&0x80 )
|
||||
{
|
||||
// signed 8-bit delta
|
||||
offset+=(char)(c<<1);
|
||||
packed++;
|
||||
packlen--;
|
||||
}
|
||||
else if ( c&0x40 )
|
||||
{
|
||||
if ( packlen < 2 )
|
||||
goto BADDATA;
|
||||
// 15-bit unsigned(?) delta
|
||||
// comment in PalmOS_Startup.cpp says "unsigned" but they cast it to a signed short...
|
||||
uint32 o1 = swap16(*(ushort*)packed);
|
||||
packed += 2;
|
||||
packlen -= 2;
|
||||
offset += (short)(o1<<2)>>1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( packlen < 4 )
|
||||
goto BADDATA;
|
||||
// direct signed 31-bit offset
|
||||
offset = relocbase+(int32(swap32(*(int32*)packed)<<2)>>1);
|
||||
packed += 4;
|
||||
packlen -= 4;
|
||||
}
|
||||
for ( int j=0; j < 4; j++ )
|
||||
if ( !is_loaded(offset+j) )
|
||||
put_byte(offset+j, 0);
|
||||
fd.off = get_dword(offset);
|
||||
if ( code )
|
||||
{
|
||||
fd.set(offset);
|
||||
auto_make_proc(targetbase+fd.off);
|
||||
if ( get_word(offset-2) == 0x4EF9 ) // jump opcode?
|
||||
auto_make_proc(offset-2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd.set_base(targetbase);
|
||||
fd.set(offset);
|
||||
}
|
||||
// msg("Relocation %d at %08X: %08X -> %08X\n", i, offset-relocbase, fd.off, targetbase+fd.off);
|
||||
}
|
||||
return packed;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// unpack rle data from the buffer packed at file position fpos to ea cea
|
||||
// return new position in the buffer and update cea
|
||||
static uchar *unpack_rle(uchar *packed, size_t &packlen, ea_t &cea, qoff64_t fpos)
|
||||
{
|
||||
const uchar *packed_sav = packed;
|
||||
while ( 1 )
|
||||
{
|
||||
if ( packlen < 1 )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return NULL;
|
||||
}
|
||||
uchar buf[256];
|
||||
buf[0] = '\0'; // shutup lint
|
||||
uchar cnt = *packed++;
|
||||
packlen--;
|
||||
if ( cnt == 0 )
|
||||
break;
|
||||
if ( cnt & 0x80 )
|
||||
{
|
||||
cnt = (cnt & 0x7F) + 1;
|
||||
if ( packlen < cnt )
|
||||
goto BADDATA;
|
||||
mem2base(packed, cea, cea+cnt, fpos+(packed-packed_sav));
|
||||
packed += cnt;
|
||||
packlen -= cnt;
|
||||
cea += cnt;
|
||||
continue;
|
||||
}
|
||||
if ( cnt & 0x40 )
|
||||
{
|
||||
cnt = (cnt & 0x3F) + 1;
|
||||
memset(buf, 0, cnt);
|
||||
}
|
||||
else if ( cnt & 0x20 )
|
||||
{
|
||||
if ( packlen < 1 )
|
||||
goto BADDATA;
|
||||
cnt = (cnt & 0x1F) + 2;
|
||||
memset(buf, *packed++, cnt);
|
||||
packlen--;
|
||||
}
|
||||
else if ( cnt & 0x10 )
|
||||
{
|
||||
cnt = (cnt & 0x0F) + 1;
|
||||
memset(buf, 0xFF, cnt);
|
||||
}
|
||||
else if ( cnt == 1 )
|
||||
{
|
||||
if ( packlen < 2 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0xFF;
|
||||
buf[5] = 0xFF;
|
||||
buf[6] = *packed++;
|
||||
buf[7] = *packed++;
|
||||
packlen -= 2;
|
||||
cnt = 8;
|
||||
}
|
||||
else if ( cnt == 2 )
|
||||
{
|
||||
if ( packlen < 3 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0xFF;
|
||||
buf[5] = *packed++;
|
||||
buf[6] = *packed++;
|
||||
buf[7] = *packed++;
|
||||
cnt = 8;
|
||||
packlen -= 3;
|
||||
}
|
||||
else if ( cnt == 3 )
|
||||
{
|
||||
if ( packlen < 3 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0xA9;
|
||||
buf[1] = 0xF0;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = *packed++;
|
||||
buf[5] = *packed++;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = *packed++;
|
||||
cnt = 8;
|
||||
packlen -= 3;
|
||||
}
|
||||
else if ( cnt == 4 )
|
||||
{
|
||||
if ( packlen < 4 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0xA9;
|
||||
buf[1] = 0xF0;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = *packed++;
|
||||
buf[4] = *packed++;
|
||||
buf[5] = *packed++;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = *packed++;
|
||||
cnt = 8;
|
||||
packlen -= 4;
|
||||
}
|
||||
mem2base(buf, cea, cea+cnt, -1);
|
||||
cea += cnt;
|
||||
}
|
||||
return packed;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static size_t unpack_data0000(
|
||||
linput_t *li,
|
||||
qoff64_t fpos,
|
||||
size_t size,
|
||||
ea_t ea,
|
||||
const code0000_t &code0000,
|
||||
ea_t code1ea,
|
||||
ea_t &a5)
|
||||
{
|
||||
if ( size < 4 )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return 0;
|
||||
}
|
||||
bytevec_t packed_buf;
|
||||
packed_buf.resize(size);
|
||||
uchar *packed = packed_buf.begin();
|
||||
qlseek(li, fpos);
|
||||
lread(li, packed, size);
|
||||
size_t usize = code0000.nBytesAboveA5 + code0000.nBytesBelowA5; // total data size
|
||||
enable_flags(ea, ea+usize, STT_CUR);
|
||||
|
||||
packed += sizeof(uint32); // skip initializers size
|
||||
size -= sizeof(uint32);
|
||||
|
||||
a5 = ea+code0000.nBytesBelowA5;
|
||||
ea_t cea;
|
||||
for ( int i=0; i < 3; i++ )
|
||||
{
|
||||
if ( size < 4 )
|
||||
goto BADDATA;
|
||||
int32 offset = swap32(*(uint32*)packed); // offset from A5
|
||||
packed += sizeof(uint32);
|
||||
size -= sizeof(uint32);
|
||||
cea = a5 + offset;
|
||||
if ( cea < ea )
|
||||
{
|
||||
// can happen when code 0 resource is not present (e.g. prc-tools GLib-type shared libs)
|
||||
if ( i != 0 )
|
||||
loader_failure("Error while decompressing data 0");
|
||||
cea = ea;
|
||||
a5 = ea-offset;
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
}
|
||||
if ( usize < cea-ea )
|
||||
usize = size_t(cea-ea);
|
||||
}
|
||||
|
||||
if ( a5 > ea + usize - 1 )
|
||||
{
|
||||
// allocate one extra byte for A5
|
||||
enable_flags(ea+usize, ea+usize+1, STT_CUR);
|
||||
usize++;
|
||||
}
|
||||
create_byte(a5,1);
|
||||
if ( a5 != ea )
|
||||
add_pgm_cmt("A5 register does not point to the start of the data segment\n"
|
||||
"The file should not be recompiled using Pila\n");
|
||||
set_name(a5,"A5BASE",SN_NOCHECK|SN_AUTO);
|
||||
set_cmt(a5,"A5 points here",0);
|
||||
// TODO: find undefined bytes and set them to zero
|
||||
// this is done by Palm OS loader and some programs depend on it
|
||||
|
||||
// process relocations
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a5 to a5
|
||||
// msg("Relocations: data to data\n");
|
||||
packed = apply_relocs(packed, size, a5, a5);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a5 to code
|
||||
// msg("Relocations: data to code1\n");
|
||||
packed = apply_relocs(packed, size, a5, code1ea, true);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
return usize;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// CodeWarrior A4 data layout:
|
||||
//
|
||||
// 0..3: 0x00000000
|
||||
// 4..7: size of "above A4" region
|
||||
// 8..11: size of "below A4" region
|
||||
// 12..N-1: compressed "below A4" data
|
||||
// N..N+3: size of "near above A4" region
|
||||
// N+4..O-1: compressed "near above A4" data
|
||||
// O..O+3: size of "far above A4" region
|
||||
// O+4..P-1: compressed "far above A4" data
|
||||
// then the relocations:
|
||||
// 1) A4 -> A4
|
||||
// 2) A4 -> A5
|
||||
// 3) A4 -> code0001
|
||||
// 4) A5 -> A4
|
||||
|
||||
static size_t unpack_data0001(linput_t *li, qoff64_t fpos, size_t size, ea_t ea, ea_t a5, ea_t code1ea, ea_t &a4)
|
||||
{
|
||||
if ( size < 3 * sizeof(uint32) )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return 0;
|
||||
}
|
||||
bytevec_t packed_buf;
|
||||
packed_buf.resize(size);
|
||||
uchar *packed = packed_buf.begin();
|
||||
qlseek(li, fpos);
|
||||
lread(li, packed, size);
|
||||
packed += sizeof(uint32); // skip the 0
|
||||
size -= sizeof(uint32);
|
||||
|
||||
int32 above = swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
int32 below = swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
size_t usize = above - below; // unpacked size
|
||||
if ( below & 1 )
|
||||
usize++;
|
||||
|
||||
ea_t cea = ea;
|
||||
a4 = ea-below;
|
||||
if ( below & 1 )
|
||||
a4++;
|
||||
enable_flags(ea, ea+usize, STT_CUR);
|
||||
create_byte(a4,1);
|
||||
set_name(a4,"A4BASE",SN_NOCHECK|SN_AUTO);
|
||||
set_cmt(a4,"A4 points here",0);
|
||||
|
||||
// unpack below a4
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
|
||||
// unpack near above a4
|
||||
if ( size < sizeof(int32) )
|
||||
goto BADDATA;
|
||||
cea = a4 + swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
|
||||
// unpack far above a4
|
||||
if ( size < sizeof(int32) )
|
||||
goto BADDATA;
|
||||
cea = a4 + swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
|
||||
cea -= ea;
|
||||
if ( usize < cea )
|
||||
usize = (size_t)cea;
|
||||
|
||||
// process relocations
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a4 to a4
|
||||
// msg("Relocations: a4 to a4\n");
|
||||
packed = apply_relocs(packed, size, a4, a4);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a4 to a5
|
||||
// msg("Relocations: a4 to a5\n");
|
||||
packed = apply_relocs(packed, size, a4, a5);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a4 to code1
|
||||
// msg("Relocations: a4 to code1\n");
|
||||
packed = apply_relocs(packed, size, a4, code1ea, true);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a5 to a4
|
||||
// msg("Relocations: a5 to a4\n");
|
||||
packed = apply_relocs(packed, size, a5, a4);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
return usize;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void fix_jumptables(ea_t ea1, ea_t /*ea2*/, sel_t sel, ea_t a5, ea_t a4)
|
||||
{
|
||||
// msg("Fixing additional code segment at %08X\n",ea1);
|
||||
// from PalmOS_Startup.cpp
|
||||
/*
|
||||
struct SegmentHeader { // the structure of a segment header
|
||||
short jtsoffset; // A5 relative offset of this segments jump table (short version)
|
||||
short jtentries; // number of entries in this segments jump table
|
||||
int32 jtloffset; // A5 relative offset of this segments jump table (long version)
|
||||
int32 xrefoffset; // offset of xref data in this CODE resource
|
||||
char code[]; // the code
|
||||
};
|
||||
struct JumpTableEntry { // the structure of a jumptable entry
|
||||
short jumpinstruction; // instruction: jmp routine
|
||||
int32 jumpaddress; // absolute or relative address of rountine
|
||||
};*/
|
||||
|
||||
short jtsoffset = get_word(ea1);
|
||||
int32 jtloffset = get_dword(ea1+4);
|
||||
if ( jtsoffset != jtloffset )
|
||||
{
|
||||
// msg("Doesn't look like a CodeWarrior code segment\n");
|
||||
return;
|
||||
}
|
||||
// find the jumptable
|
||||
ea_t jt_start;
|
||||
if ( a4 != BADADDR && get_word(a4+jtloffset) == 0x4EF9 ) // jmp opcode
|
||||
{
|
||||
jt_start = a4+jtloffset;
|
||||
create_word(ea1,2);
|
||||
create_dword(ea1+4,4);
|
||||
op_offset(ea1, 0, REF_OFF16, BADADDR, a4);
|
||||
op_offset(ea1+4, 0, REF_OFF32, BADADDR, a4);
|
||||
}
|
||||
else if ( get_word(a5+jtloffset) == 0x4EF9 ) // jmp opcode
|
||||
{
|
||||
jt_start = a5+jtloffset;
|
||||
create_word(ea1,2);
|
||||
create_dword(ea1+4,4);
|
||||
op_offset(ea1, 0, REF_OFF16, BADADDR, a5);
|
||||
op_offset(ea1+4, 0, REF_OFF32, BADADDR, a5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// msg("Could not find the jump table!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
create_word(ea1+2,2);
|
||||
create_dword(ea1+8,4);
|
||||
op_offset(ea1+8, 0, REF_OFF32, BADADDR, ea1);
|
||||
set_cmt(ea1, "Short jump table offset", 0);
|
||||
set_cmt(ea1+2, "Number of jump table entries", 0);
|
||||
set_cmt(ea1+4, "Long jump table offset", 0);
|
||||
set_cmt(ea1+8, "Offset to xref data", 0);
|
||||
|
||||
fixup_data_t fd(FIXUP_OFF32);
|
||||
fd.sel = sel;
|
||||
ea_t jt_addr=jt_start;
|
||||
short jtentries = get_word(ea1+2);
|
||||
while ( jtentries-- )
|
||||
{
|
||||
fd.off = get_dword(jt_addr+2);
|
||||
fd.set(jt_addr+2);
|
||||
// a little heuristic: does the jump point to code?
|
||||
if ( get_word(ea1+fd.off) == 0x4E56 // link a6,x
|
||||
|| get_word(ea1+fd.off) == 0x06AF ) // addi.l x, 4(sp)
|
||||
{
|
||||
auto_make_proc(ea1+fd.off);
|
||||
auto_make_proc(jt_addr);
|
||||
}
|
||||
jt_addr+=6;
|
||||
}
|
||||
// TODO: hide the table?
|
||||
// add_hidden_range(jt_start, jt_addr, "Jumptable for segment NNN", "", "", 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void doCodeOffset(ea_t ea, ea_t base)
|
||||
{
|
||||
create_dword(ea,4);
|
||||
uint32 off = get_dword(ea);
|
||||
op_offset(ea, 0, REF_OFF32, BADADDR, base, off&1);
|
||||
ea_t target = base+off;
|
||||
if ( off&1 )// last bit set: offset to thumb code
|
||||
{
|
||||
target &= (~1); // remove last bit
|
||||
// set_sreg_at_next_code(target,BADADDR,str2reg("T"),1);
|
||||
split_sreg_range(target,str2reg("T"),1,SR_auto,true);
|
||||
}
|
||||
auto_make_proc(target);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void fixArmCW(ea_t start_ea, ea_t end_ea)
|
||||
{
|
||||
// check for codewarrior relocation info
|
||||
/*
|
||||
typedef struct PnoHeaderType {
|
||||
00 UInt32 startupCode[8]; // changes based on the instruction count in startup code
|
||||
20 UInt32 pnoMain; // offset to ARMletMain routine
|
||||
24 UInt32 signature; // special PNO signature value
|
||||
28 UInt32 dataStart; // offset to start of initialized data
|
||||
2C UInt32 roDataStart; // offset to start of read-only initialized data
|
||||
30 UInt32 bssStart; // offset to start of uninitialized data
|
||||
34 UInt32 bssEnd; // offset to end of uninitialized data
|
||||
38 UInt32 codeRelocsStart; // offset to start of data-to-code relocation list
|
||||
3C UInt32 codeRelocsEnd; // offset to end of data-to-code relocation list
|
||||
40 UInt32 dataRelocsStart; // offset to start of data-to-data relocation list
|
||||
44 UInt32 dataRelocsEnd; // offset to end of data-to-data relocation list
|
||||
48 UInt32 altEntryCode[8]; // changes based on the instruction count in alternate entry code
|
||||
68
|
||||
} PnoHeaderType;
|
||||
*/
|
||||
const char *const comments[] =
|
||||
{
|
||||
"offset to ARMletMain routine",
|
||||
"special PNO signature value",
|
||||
"offset to start of initialized data",
|
||||
"offset to start of read-only initialized data",
|
||||
"offset to start of uninitialized data",
|
||||
"offset to end of uninitialized data",
|
||||
"offset to start of data-to-code relocation list",
|
||||
"offset to end of data-to-code relocation list",
|
||||
"offset to start of data-to-data relocation list",
|
||||
"offset to end of data-to-data relocation list",
|
||||
};
|
||||
|
||||
if ( end_ea-start_ea < 0x68 )
|
||||
return;
|
||||
for ( int i=0x20; i < 0x48; i+=4 )
|
||||
{
|
||||
create_dword(start_ea+i,4);
|
||||
if ( i == 0x24 )
|
||||
op_chr(start_ea+i, 0);
|
||||
else
|
||||
op_offset(start_ea+i, 0, REF_OFF32, BADADDR, start_ea);
|
||||
set_cmt(start_ea+i, comments[(i-0x20)/4],0);
|
||||
}
|
||||
auto_make_proc(start_ea);
|
||||
auto_make_proc(start_ea+0x48);
|
||||
doCodeOffset(start_ea+0x20,start_ea);
|
||||
|
||||
// do relocs
|
||||
ea_t cur = start_ea+get_dword(start_ea+0x38);
|
||||
ea_t end = start_ea+get_dword(start_ea+0x3C);
|
||||
for ( ; cur < end; cur+=4 )
|
||||
{
|
||||
create_dword(cur,4);
|
||||
op_offset(cur, 0, REF_OFF32, BADADDR, start_ea);
|
||||
doCodeOffset(start_ea+get_dword(cur), start_ea);
|
||||
}
|
||||
cur = start_ea+get_dword(start_ea+0x40);
|
||||
end = start_ea+get_dword(start_ea+0x44);
|
||||
for ( ; cur < end; cur+=4 )
|
||||
{
|
||||
create_dword(cur,4);
|
||||
op_offset(cur, 0, REF_OFF32, BADADDR, start_ea);
|
||||
ea_t o = start_ea+get_dword(cur);
|
||||
create_dword(o,4);
|
||||
op_offset(o, 0, REF_OFF32, BADADDR, start_ea);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// check for 'cdwr' signature
|
||||
bool isCWseg(linput_t *li, uint32 offset)
|
||||
{
|
||||
qlseek(li, offset + 0x24);
|
||||
uchar sig[4];
|
||||
qlread(li, sig, 4);
|
||||
return sig[0] == 'r'
|
||||
&& sig[1] == 'w'
|
||||
&& sig[2] == 'd'
|
||||
&& sig[3] == 'c';
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort neflags, const char * fileformatname)
|
||||
{
|
||||
int i;
|
||||
bool armCode = strcmp(fileformatname, PRC_ARM) == 0;
|
||||
bool manualMode = (neflags & NEF_MAN) != 0; // don't do any extra processing if set
|
||||
sel_t dgroup = BADSEL;
|
||||
|
||||
set_processor_type(armCode ? "ARM" : "68K", SETPROC_LOADER);
|
||||
set_target_assembler(armCode ? 0 : 2); // Generic ARM assembler/PalmPilot assembler Pila
|
||||
DatabaseHdrType h;
|
||||
lread(li,&h,sizeof(h));
|
||||
swap_prc(h);
|
||||
|
||||
qvector<ResourceMapEntry> re;
|
||||
re.resize(h.numRecords);
|
||||
lread(li, re.begin(), sizeof(ResourceMapEntry) * h.numRecords);
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
swap_resource_map_entry(re[i]);
|
||||
|
||||
code0000_t code0000 = { 0, 0 };
|
||||
if ( !armCode )
|
||||
{
|
||||
// sortResources(re, h.numRecords);
|
||||
// determine the bss size
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
if ( re[i].fcType == PILOT_RSC_CODE && re[i].id == 0 ) // code0000
|
||||
{
|
||||
qlseek(li, re[i].ulOffset);
|
||||
lread(li, &code0000, sizeof(code0000));
|
||||
swap_code0000(&code0000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ea_t a5 = BADADDR, a4 = BADADDR, code1ea = BADADDR;
|
||||
ea_t datastart = BADADDR;
|
||||
|
||||
// load the segments
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
// don't load known UI resources when asked not to
|
||||
if ( !(NEF_RSCS & neflags) && isKnownResource(re[i].fcType) )
|
||||
continue;
|
||||
// skip ARM chunks in 68K mode
|
||||
if ( !armCode && (re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL) )
|
||||
continue;
|
||||
|
||||
uint64 size;
|
||||
if ( i == (h.numRecords-1) )
|
||||
size = qlsize(li);
|
||||
else
|
||||
size = re[i+1].ulOffset;
|
||||
if ( size < re[i].ulOffset )
|
||||
loader_failure("Invalid file structure");
|
||||
size -= re[i].ulOffset;
|
||||
ea_t ea1 = (inf_get_max_ea() + 0xF) & ~0xF;
|
||||
ea_t ea2 = ea1 + size;
|
||||
|
||||
char segname[10];
|
||||
qsnprintf(segname, sizeof(segname), "%4.4s%04X", (char*)&re[i].fcType, re[i].id);
|
||||
const char *sclass = "RSC";
|
||||
|
||||
if ( armCode )
|
||||
{
|
||||
// load only ARM segments in ARM mode
|
||||
if ( re[i].fcType != PILOT_RSC_ARMC && re[i].fcType != PILOT_RSC_ARMCL )
|
||||
continue;
|
||||
|
||||
bool bCodeWarrior = isCWseg(li, re[i].ulOffset);
|
||||
|
||||
ea_t start_ea=ea1;
|
||||
file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE);
|
||||
int sel = i+1;
|
||||
if ( bCodeWarrior && !manualMode )
|
||||
{
|
||||
// load all sequential chunks as one segment
|
||||
while ( i < h.numRecords-1 && re[i].fcType == re[i+1].fcType && re[i].id + 1 == re[i+1].id && !isCWseg(li, re[i+1].ulOffset) )
|
||||
{
|
||||
i++;
|
||||
if ( i == (h.numRecords-1) )
|
||||
size = qlsize(li);
|
||||
else
|
||||
size = re[i+1].ulOffset;
|
||||
if ( size < re[i].ulOffset )
|
||||
loader_failure("Invalid file structure");
|
||||
size -= re[i].ulOffset;
|
||||
ea1 = ea2; // TODO: check if pnoloader.c does alignment
|
||||
ea2 = ea1 + size;
|
||||
file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE);
|
||||
}
|
||||
}
|
||||
set_selector(sel, start_ea >> 4);
|
||||
if ( !add_segm(sel, start_ea, ea2, segname, CLASS_CODE, ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
|
||||
// set DS for the segment to itself
|
||||
set_default_sreg_value(get_segm_by_sel(sel), str2reg("DS"), sel);
|
||||
if ( bCodeWarrior )
|
||||
fixArmCW(start_ea, ea2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( re[i].fcType == PILOT_RSC_CODE )
|
||||
{
|
||||
if ( re[i].id == 0 && !manualMode )
|
||||
continue; // skip code0000 resource
|
||||
sclass = CLASS_CODE;
|
||||
if ( re[i].id == 1 )
|
||||
{
|
||||
inf_set_start_cs(i + 1);
|
||||
inf_set_start_ip(0);
|
||||
code1ea = ea1;
|
||||
}
|
||||
}
|
||||
else if ( re[i].fcType == PILOT_RSC_LIBR || re[i].fcType == PILOT_RSC_GLIB )
|
||||
{
|
||||
sclass = CLASS_CODE;
|
||||
if ( re[i].id == 0 )
|
||||
{
|
||||
inf_set_start_cs(i + 1);
|
||||
inf_set_start_ip(0);
|
||||
code1ea = ea1;
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to decompress stuff
|
||||
if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 0 )
|
||||
{
|
||||
sclass = CLASS_DATA;
|
||||
dgroup = i + 1;
|
||||
size_t usize = unpack_data0000(li, re[i].ulOffset, size, ea1, code0000, code1ea, a5);
|
||||
ea2 = ea1 + usize;
|
||||
datastart = ea1;
|
||||
}
|
||||
else if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 1 && !manualMode )
|
||||
{
|
||||
sclass = CLASS_DATA;
|
||||
size_t usize = unpack_data0001(li, re[i].ulOffset, size, ea1, a5, code1ea, a4);
|
||||
ea2 = ea1 + usize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise just load it as-is
|
||||
file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE);
|
||||
}
|
||||
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = ea1;
|
||||
s.end_ea = ea2;
|
||||
s.sel = i+1;
|
||||
s.bitness = 1; // 32bit
|
||||
set_selector(i+1, ea1 >> 4);
|
||||
if ( !add_segm_ex(&s, segname, sclass, ADDSEG_FILLGAP|ADDSEG_OR_DIE|ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !manualMode && !armCode )
|
||||
{
|
||||
// check if first dword is 1; if so, skip it
|
||||
if ( get_dword(code1ea) == 1 )
|
||||
{
|
||||
// codewarrior startup
|
||||
static const uchar pattern[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x01, // dc.l 1
|
||||
0x48, 0x7A, 0x00, 0x04, // pea $A
|
||||
0x06, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, // addi.l #(__Startup__-$A),(sp)
|
||||
0x4E, 0x75, // rts
|
||||
};
|
||||
if ( equal_bytes(code1ea, pattern, SKIP_FF_MASK, sizeof(pattern), true) )
|
||||
{
|
||||
plan_to_apply_idasgn("cwpalm.sig");
|
||||
}
|
||||
create_dword(code1ea, 4);
|
||||
inf_set_start_ip(4);
|
||||
}
|
||||
// is main code segment GLib?
|
||||
if ( inf_get_start_cs() > 0
|
||||
&& re[int(inf_get_start_cs()-1)].fcType == PILOT_RSC_GLIB
|
||||
&& a4 == BADADDR
|
||||
&& datastart != BADADDR )
|
||||
{
|
||||
// GLib's a4 points at the start of data segment
|
||||
a4 = datastart;
|
||||
create_byte(a4, 1);
|
||||
set_name(a4, "A4BASE", SN_NOCHECK|SN_AUTO);
|
||||
set_cmt(a4, "A4 points here", 0);
|
||||
}
|
||||
// check for CodeWarrior's jumptables in additional code segments and fix them up
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
if ( re[i].fcType == PILOT_RSC_CODE && re[i].id > 1 )
|
||||
{
|
||||
segment_t *seg = get_segm_by_sel(i+1);
|
||||
if ( seg != NULL )
|
||||
fix_jumptables(seg->start_ea, seg->end_ea, i+1, a5, a4);
|
||||
}
|
||||
}
|
||||
// TODO: handle prc-tools and multilink's 'rloc' segments
|
||||
}
|
||||
|
||||
if ( dgroup != BADSEL )
|
||||
set_default_dataseg(dgroup); // input: selector
|
||||
describe_all(h);
|
||||
exec_system_script("pilot.idc");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// it is impossible to use ph.id,
|
||||
// the processor module is not loaded yet
|
||||
inline bool is_arm_specified(void)
|
||||
{
|
||||
return strnieq(inf_get_procname().c_str(), "ARM", 3);
|
||||
}
|
||||
|
||||
inline bool is_68k_specified(void)
|
||||
{
|
||||
char pname[IDAINFO_PROCNAME_SIZE];
|
||||
inf_get_procname(pname, sizeof(pname));
|
||||
return strnieq(pname, "68K", 3)
|
||||
|| strnieq(pname, "68000", 5)
|
||||
|| strnieq(pname, "68010", 5)
|
||||
|| strnieq(pname, "68020", 5)
|
||||
|| strnieq(pname, "68030", 5)
|
||||
|| strnieq(pname, "68040", 5)
|
||||
|| strnieq(pname, "68330", 5)
|
||||
|| strnieq(pname, "68882", 5)
|
||||
|| strnieq(pname, "68851", 5)
|
||||
|| strnieq(pname, "ColdFire", 8);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
static int n = 0;
|
||||
int k = is_prc_file(li);
|
||||
if ( k == 0 )
|
||||
return 0;
|
||||
int ftype = 0;
|
||||
if ( n == 1 )
|
||||
{
|
||||
if ( k == 2 ) // has ARM segments?
|
||||
{
|
||||
*fileformatname = PRC_ARM;
|
||||
*processor = "ARM";
|
||||
ftype = f_PRC;
|
||||
if ( is_arm_specified() )
|
||||
ftype |= ACCEPT_FIRST;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n++;
|
||||
*fileformatname = PRC_68K;
|
||||
*processor = "68K";
|
||||
ftype = f_PRC|ACCEPT_CONTINUE;
|
||||
if ( is_68k_specified() )
|
||||
ftype |= ACCEPT_FIRST;
|
||||
}
|
||||
return ftype;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
loader_t LDSC =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
0, // loader flags
|
||||
//
|
||||
// check input file format. if recognized, then return 1
|
||||
// and fill 'fileformatname'.
|
||||
// otherwise return 0
|
||||
//
|
||||
accept_file,
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
load_file,
|
||||
//
|
||||
// create output file from the database.
|
||||
// this function may be absent.
|
||||
//
|
||||
NULL,
|
||||
// take care of a moved segment (fix up relocations, for example)
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
148
idasdk76/ldr/pilot/pilot.hpp
Normal file
148
idasdk76/ldr/pilot/pilot.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PILOT_H
|
||||
#define __PILOT_H
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define PRC_68K "PalmPilot program file (68K)"
|
||||
#define PRC_ARM "PalmPilot program file (ARM)"
|
||||
|
||||
// Regular resources:
|
||||
|
||||
#define PILOT_RSC_CODE 0x65646F63L // "code\0\0\0\1" program code
|
||||
#define PILOT_RSC_PREF 0x66657270L // "pref\0\0\0\0" preferences (not used yet)
|
||||
#define PILOT_RSC_DATA 0x61746164L // "data\0\0\0\0" image of global data
|
||||
#define PILOT_RSC_LIBR 0x7262696CL // "libr" SysLib-type shared library code
|
||||
#define PILOT_RSC_GLIB 0x62694C47L // "GLib" PRC-Tools GLib-type shared library code
|
||||
#define PILOT_RSC_RLOC 0x636F6C72L // "rloc" PRC-Tools and Multilink relocations
|
||||
#define PILOT_RSC_ARMC 0x434D5241L // "ARMC" ARM native code
|
||||
#define PILOT_RSC_ARMCL 0x636D7261L // "armc" ARM native code
|
||||
|
||||
// UI resources:
|
||||
|
||||
#define PILOT_RSC_MBAR 0x5241424DL // "MBAR" Menu bar
|
||||
#define PILOT_RSC_MENU 0x554E454DL // "MENU" Menu options
|
||||
#define PILOT_RSC_ICON 0x4E494174L // "tAIN" Application icon name
|
||||
#define PILOT_RSC_AIB 0x42494174L // "tAIB" Application icon bitmap
|
||||
#define PILOT_RSC_AIS 0x53494174L // "tAIS" Application information string
|
||||
#define PILOT_RSC_ALERT 0x746C6154L // "Talt" Alert
|
||||
#define PILOT_RSC_BITMAP 0x706D6254L // "Tbmp" Bitmap
|
||||
#define PILOT_RSC_BUTTON 0x4E544274L // "tBTN" Button
|
||||
#define PILOT_RSC_CHECK 0x58424374L // "tCBX" Check box
|
||||
#define PILOT_RSC_FBM 0x4D424674L // "tFBM" Form bitmap
|
||||
#define PILOT_RSC_FIELD 0x444C4674L // "tFLD" Field
|
||||
#define PILOT_RSC_FORM 0x4D524674L // "tFRM" Form
|
||||
#define PILOT_RSC_GADGET 0x54444774L // "tGDT" Gadget
|
||||
#define PILOT_RSC_GRAFF 0x49534774L // "tGSI" Graffiti Shift
|
||||
#define PILOT_RSC_LABEL 0x4C424C74L // "tLBL" Label
|
||||
#define PILOT_RSC_LIST 0x54534C74L // "tLST" List box
|
||||
#define PILOT_RSC_PUSH 0x4E425074L // "tPBN" Push button
|
||||
#define PILOT_RSC_POPUPL 0x4C555074L // "tPUL" Popup list
|
||||
#define PILOT_RSC_POPUPT 0x54555074L // "tPUT" Popup trigger
|
||||
#define PILOT_RSC_REPEAT 0x50455274L // "tREP" Repeating control
|
||||
#define PILOT_RSC_SELECT 0x544C5374L // "tSLT" Selector trigger
|
||||
#define PILOT_RSC_STRING 0x52545374L // "tSTR" String
|
||||
#define PILOT_RSC_TABLE 0x4C425474L // "tTBL" Table
|
||||
#define PILOT_RSC_TITLE 0x4C545474L // "tTTL" Title
|
||||
#define PILOT_RSC_VER 0x72657674L // "tver" Version number string
|
||||
|
||||
|
||||
typedef uchar Byte;
|
||||
typedef ushort Word;
|
||||
typedef uint32 DWord;
|
||||
typedef DWord LocalID;
|
||||
|
||||
//
|
||||
// Header of PRC file:
|
||||
//
|
||||
|
||||
struct DatabaseHdrType
|
||||
{
|
||||
Byte name[32]; // name of database
|
||||
#define PILOT_CREATOR_PILA 0x616C6950L // "Pila"
|
||||
Word attributes; // database attributes
|
||||
#define dmHdrAttrResDB 0x0001 // Resource database
|
||||
#define dmHdrAttrReadOnly 0x0002 // Read Only database
|
||||
#define dmHdrAttrAppInfoDirty 0x0004 // Set if Application Info block is dirty
|
||||
// Optionally supported by an App's conduit
|
||||
#define dmHdrAttrBackup 0x0008 // Set if database should be backed up to PC if
|
||||
// no app-specific synchronization conduit has
|
||||
// been supplied.
|
||||
#define dmHdrAttrOpen 0x8000 // Database not closed properly
|
||||
Word version; // version of database
|
||||
DWord creationDate; // creation date of database
|
||||
DWord modificationDate; // latest modification date
|
||||
DWord lastBackupDate; // latest backup date
|
||||
DWord modificationNumber; // modification number of database
|
||||
LocalID appInfoID; // application specific info
|
||||
LocalID sortInfoID; // app specific sorting info
|
||||
DWord type; // database type
|
||||
#define PILOT_TYPE_APPL 0x6C707061L // "appl"
|
||||
DWord id; // program id
|
||||
DWord uniqueIDSeed; // used to generate unique IDs.
|
||||
// Note that only the low order
|
||||
// 3 bytes of this is used (in
|
||||
// RecordEntryType.uniqueID).
|
||||
// We are keeping 4 bytes for
|
||||
// alignment purposes.
|
||||
LocalID nextRecordListID; // local chunkID of next list
|
||||
Word numRecords; // number of records in this list
|
||||
};
|
||||
|
||||
//
|
||||
// Each resource has the following entry:
|
||||
//
|
||||
struct ResourceMapEntry
|
||||
{
|
||||
uint32 fcType;
|
||||
ushort id;
|
||||
uint32 ulOffset;
|
||||
};
|
||||
|
||||
|
||||
// Pilot bitmap format (also format of icon)
|
||||
struct pilot_bitmap_t
|
||||
{
|
||||
ushort cx;
|
||||
ushort cy;
|
||||
ushort cbRow;
|
||||
ushort ff;
|
||||
ushort ausUnk[4];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* code0000[long 0] nBytesAboveA5
|
||||
* code0000[long 1] nBytesBelowA5
|
||||
*/
|
||||
struct code0000_t
|
||||
{
|
||||
uint32 nBytesAboveA5;
|
||||
uint32 nBytesBelowA5;
|
||||
};
|
||||
|
||||
// pref0000
|
||||
|
||||
struct pref0000_t
|
||||
{
|
||||
ushort flags;
|
||||
#define sysAppLaunchFlagNewThread 0x0001
|
||||
#define sysAppLaunchFlagNewStack 0x0002
|
||||
#define sysAppLaunchFlagNewGlobals 0x0004
|
||||
#define sysAppLaunchFlagUIApp 0x0008
|
||||
#define sysAppLaunchFlagSubCall 0x0010
|
||||
uint32 stack_size;
|
||||
uint32 heap_size;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // __PILOT_H
|
||||
216
idasdk76/ldr/pilot/pilot.idc
Normal file
216
idasdk76/ldr/pilot/pilot.idc
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// This file is executed when a PalmPilot program is loaded.
|
||||
// You may customize it as you wish.
|
||||
//
|
||||
// TODO:
|
||||
// - decompilation of various resource types
|
||||
// (we don't have any information on the formats)
|
||||
//
|
||||
|
||||
#include <idc.idc>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Process each resource and make some routine tasks
|
||||
//
|
||||
static process_segments()
|
||||
{
|
||||
auto ea,segname,prefix;
|
||||
|
||||
for ( ea=get_first_seg(); ea != BADADDR; ea=get_next_seg(ea) )
|
||||
{
|
||||
segname = get_segm_name(ea);
|
||||
prefix = substr(segname,0,4);
|
||||
if ( segname == "data0000" )
|
||||
{
|
||||
if ( get_wide_dword(ea) == 0xFFFFFFFF )
|
||||
{
|
||||
create_dword(ea);
|
||||
set_cmt(ea,"Loader stores SysAppInfoPtr here", 0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "TRAP" )
|
||||
{
|
||||
create_word(ea);
|
||||
op_hex(ea,0);
|
||||
set_cmt(ea,"System trap function code", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "tSTR" )
|
||||
{
|
||||
create_strlit(ea,get_segm_end(ea));
|
||||
set_cmt(ea,"String resource", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "tver" )
|
||||
{
|
||||
create_strlit(ea,get_segm_end(ea));
|
||||
set_cmt(ea,"Version number string", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "tAIN" )
|
||||
{
|
||||
create_strlit(ea,get_segm_end(ea));
|
||||
set_cmt(ea,"Application icon name", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "pref" )
|
||||
{
|
||||
auto flags,cmt;
|
||||
flags = get_wide_word(ea);
|
||||
create_word(ea); op_hex(ea,0); set_name(ea,"flags");
|
||||
#define sysAppLaunchFlagNewThread 0x0001
|
||||
#define sysAppLaunchFlagNewStack 0x0002
|
||||
#define sysAppLaunchFlagNewGlobals 0x0004
|
||||
#define sysAppLaunchFlagUIApp 0x0008
|
||||
#define sysAppLaunchFlagSubCall 0x0010
|
||||
cmt = "";
|
||||
if ( flags & sysAppLaunchFlagNewThread ) cmt = cmt + "sysAppLaunchFlagNewThread\n";
|
||||
if ( flags & sysAppLaunchFlagNewStack ) cmt = cmt + "sysAppLaunchFlagNewStack\n";
|
||||
if ( flags & sysAppLaunchFlagNewGlobals) cmt = cmt + "sysAppLaunchFlagNewGlobals\n";
|
||||
if ( flags & sysAppLaunchFlagUIApp ) cmt = cmt + "sysAppLaunchFlagUIApp\n";
|
||||
if ( flags & sysAppLaunchFlagSubCall ) cmt = cmt + "sysAppLaunchFlagSubCall";
|
||||
set_cmt(ea,cmt, 0);
|
||||
ea = ea + 2;
|
||||
create_dword(ea); op_hex(ea,0); set_name(ea,"stack_size");
|
||||
ea = ea + 4;
|
||||
create_dword(ea); op_hex(ea,0); set_name(ea,"heap_size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Create a enumeration with system action codes
|
||||
//
|
||||
static make_actions()
|
||||
{
|
||||
auto id;
|
||||
id = add_enum(-1,"SysAppLaunchCmd",FF_0NUMD);
|
||||
if ( id != -1 )
|
||||
{
|
||||
set_enum_cmt(id,"Action codes",0);
|
||||
add_enum_member(id, "sysAppLaunchCmdNormalLaunch", 0, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdFind", 1, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdGoTo", 2, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSyncNotify", 3, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdTimeChange", 4, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSystemReset", 5, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdAlarmTriggered", 6, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdDisplayAlarm", 7, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdCountryChange", 8, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSyncRequest", 9, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSaveData", 10, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdInitDatabase", 11, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSyncCallApplication", 12, -1);
|
||||
set_enum_member_cmt(get_enum_member(id, 0, 0, -1), "Normal Launch", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 1, 0, -1), "Find string", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 2, 0, -1), "Launch and go to a particular record", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 3, 0, -1),
|
||||
"Sent to apps whose databases changed\n"
|
||||
"during HotSync after the sync has\n"
|
||||
"been completed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 4, 0, -1), "The system time has changed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 5, 0, -1), "Sent after System hard resets", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 6, 0, -1), "Schedule next alarm", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 7, 0, -1), "Display given alarm dialog", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 8, 0, -1), "The country has changed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 9, 0, -1), "The \"HotSync\" button was pressed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 10, 0, -1),
|
||||
"Sent to running app before\n"
|
||||
"sysAppLaunchCmdFind or other\n"
|
||||
"action codes that will cause data\n"
|
||||
"searches or manipulation", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 11, 0, -1),
|
||||
"Initialize a database; sent by\n"
|
||||
"DesktopLink server to the app whose\n"
|
||||
"creator ID matches that of the database\n"
|
||||
"created in response to the \"create db\" request", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 12, 0, -1),
|
||||
"Used by DesktopLink Server command\n"
|
||||
"\"call application\"", 1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Create a enumeration with event codes
|
||||
//
|
||||
static make_events()
|
||||
{
|
||||
auto id;
|
||||
id = add_enum(-1,"events",FF_0NUMD);
|
||||
if ( id != -1 )
|
||||
{
|
||||
set_enum_cmt(id,"Event codes",0);
|
||||
add_enum_member(id, "nilEvent", 0, -1);
|
||||
add_enum_member(id,"penDownEvent", 1, -1);
|
||||
add_enum_member(id,"penUpEvent", 2, -1);
|
||||
add_enum_member(id,"penMoveEvent", 3, -1);
|
||||
add_enum_member(id,"keyDownEvent", 4, -1);
|
||||
add_enum_member(id,"winEnterEvent", 5, -1);
|
||||
add_enum_member(id,"winExitEvent", 6, -1);
|
||||
add_enum_member(id,"ctlEnterEvent", 7, -1);
|
||||
add_enum_member(id,"ctlExitEvent", 8, -1);
|
||||
add_enum_member(id,"ctlSelectEvent", 9, -1);
|
||||
add_enum_member(id,"ctlRepeatEvent", 10, -1);
|
||||
add_enum_member(id,"lstEnterEvent", 11, -1);
|
||||
add_enum_member(id,"lstSelectEvent", 12, -1);
|
||||
add_enum_member(id,"lstExitEvent", 13, -1);
|
||||
add_enum_member(id,"popSelectEvent", 14, -1);
|
||||
add_enum_member(id,"fldEnterEvent", 15, -1);
|
||||
add_enum_member(id,"fldHeightChangedEvent", 16, -1);
|
||||
add_enum_member(id,"fldChangedEvent", 17, -1);
|
||||
add_enum_member(id,"tblEnterEvent", 18, -1);
|
||||
add_enum_member(id,"tblSelectEvent", 19, -1);
|
||||
add_enum_member(id,"daySelectEvent", 20, -1);
|
||||
add_enum_member(id,"menuEvent", 21, -1);
|
||||
add_enum_member(id,"appStopEvent", 22, -1);
|
||||
add_enum_member(id,"frmLoadEvent", 23, -1);
|
||||
add_enum_member(id,"frmOpenEvent", 24, -1);
|
||||
add_enum_member(id,"frmGotoEvent", 25, -1);
|
||||
add_enum_member(id,"frmUpdateEvent", 26, -1);
|
||||
add_enum_member(id,"frmSaveEvent", 27, -1);
|
||||
add_enum_member(id,"frmCloseEvent", 28, -1);
|
||||
add_enum_member(id,"tblExitEvent", 29, -1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static main()
|
||||
{
|
||||
process_segments();
|
||||
make_actions();
|
||||
make_events();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#ifdef __undefined_symbol__
|
||||
// WE DO NOT USE IDC HOTKEYS, JUST SIMPLE KEYBOARD MACROS
|
||||
// (see IDA.CFG, macro Alt-5 for mc68k)
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Register Ctrl-R as a hotkey for "make offset from A5" command
|
||||
// (not used, simple keyboard macro is used instead, see IDA.CFG)
|
||||
//
|
||||
// There is another (manual) way to convert an operand to an offset:
|
||||
// - press Ctrl-R
|
||||
// - enter "A5BASE"
|
||||
// - press Enter
|
||||
//
|
||||
static setup_pilot()
|
||||
{
|
||||
auto h0,h1;
|
||||
h0 = "Alt-1";
|
||||
h1 = "Alt-2";
|
||||
add_idc_hotkey(h0,"a5offset0");
|
||||
add_idc_hotkey(h1,"a5offset1");
|
||||
msg("Use %s to convert the first operand to an offset from A5\n",h0);
|
||||
msg("Use %s to convert the second operand to an offset from A5\n",h1);
|
||||
}
|
||||
|
||||
static a5offset0(void) { op_plain_offset(get_screen_ea(),0,get_name_ea_simple("A5BASE")); }
|
||||
static a5offset1(void) { op_plain_offset(get_screen_ea(),1,get_name_ea_simple("A5BASE")); }
|
||||
|
||||
#endif // 0
|
||||
Reference in New Issue
Block a user