update to ida 7.6, add builds
This commit is contained in:
313
idasdk76/ldr/pef/common.cpp
Normal file
313
idasdk76/ldr/pef/common.cpp
Normal file
@@ -0,0 +1,313 @@
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_pef(pef_t &pef)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(pef);
|
||||
#else
|
||||
pef.formatVersion = swap32(pef.formatVersion);
|
||||
pef.dateTimeStamp = swap32(pef.dateTimeStamp);
|
||||
pef.oldDefVersion = swap32(pef.oldDefVersion);
|
||||
pef.oldImpVersion = swap32(pef.oldImpVersion);
|
||||
pef.currentVersion = swap32(pef.currentVersion);
|
||||
pef.reservedA = swap32(pef.reservedA);
|
||||
pef.sectionCount = swap16(pef.sectionCount);
|
||||
pef.instSectionCount = swap16(pef.instSectionCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_pef_section(pef_section_t &ps)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(ps);
|
||||
#else
|
||||
ps.nameOffset = swap32(ps.nameOffset);
|
||||
ps.defaultAddress = swap32(ps.defaultAddress);
|
||||
ps.totalSize = swap32(ps.totalSize);
|
||||
ps.unpackedSize = swap32(ps.unpackedSize);
|
||||
ps.packedSize = swap32(ps.packedSize);
|
||||
ps.containerOffset = swap32(ps.containerOffset);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_pef_loader(pef_loader_t &pl)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(pl);
|
||||
#else
|
||||
pl.mainSection = swap32(pl.mainSection);
|
||||
pl.mainOffset = swap32(pl.mainOffset);
|
||||
pl.initSection = swap32(pl.initSection);
|
||||
pl.initOffset = swap32(pl.initOffset);
|
||||
pl.termSection = swap32(pl.termSection);
|
||||
pl.termOffset = swap32(pl.termOffset);
|
||||
pl.importLibraryCount = swap32(pl.importLibraryCount);
|
||||
pl.totalImportedSymbolCount = swap32(pl.totalImportedSymbolCount);
|
||||
pl.relocSectionCount = swap32(pl.relocSectionCount);
|
||||
pl.relocInstrOffset = swap32(pl.relocInstrOffset);
|
||||
pl.loaderStringsOffset = swap32(pl.loaderStringsOffset);
|
||||
pl.exportHashOffset = swap32(pl.exportHashOffset);
|
||||
pl.exportHashTablePower = swap32(pl.exportHashTablePower);
|
||||
pl.exportedSymbolCount = swap32(pl.exportedSymbolCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_pef_library(pef_library_t &pil)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(pil);
|
||||
#else
|
||||
pil.nameOffset = swap32(pil.nameOffset);
|
||||
pil.oldImpVersion = swap32(pil.oldImpVersion);
|
||||
pil.currentVersion = swap32(pil.currentVersion);
|
||||
pil.importedSymbolCount = swap32(pil.importedSymbolCount);
|
||||
pil.firstImportedSymbol = swap32(pil.firstImportedSymbol);
|
||||
pil.reservedB = swap16(pil.reservedB);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_pef_reloc_header(pef_reloc_header_t &prh)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(prh);
|
||||
#else
|
||||
prh.sectionIndex = swap16(prh.sectionIndex);
|
||||
prh.reservedA = swap16(prh.reservedA);
|
||||
prh.relocCount = swap32(prh.relocCount);
|
||||
prh.firstRelocOffset = swap32(prh.firstRelocOffset);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_pef_export(pef_export_t &pe)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(pe);
|
||||
#else
|
||||
pe.classAndName = swap32(pe.classAndName);
|
||||
pe.symbolValue = swap32(pe.symbolValue);
|
||||
pe.sectionIndex = swap16(pe.sectionIndex);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
const char *get_pef_processor(const pef_t &pef)
|
||||
{
|
||||
if ( strneq(pef.architecture, PEF_ARCH_PPC, 4) ) // PowerPC
|
||||
return "ppc";
|
||||
if ( strneq(pef.architecture, PEF_ARCH_68K, 4) ) // or 68K
|
||||
return "68000";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
const char *get_pef_processor(linput_t *li)
|
||||
{
|
||||
pef_t pef;
|
||||
if ( qlread(li, &pef, sizeof(pef_t)) != sizeof(pef_t) )
|
||||
return NULL;
|
||||
swap_pef(pef);
|
||||
if ( !strneq(pef.tag1, PEF_TAG_1, 4) // Joy!
|
||||
|| !strneq(pef.tag2, PEF_TAG_2, 4) // peff
|
||||
|| pef.formatVersion != PEF_VERSION ) // 1
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return get_pef_processor(pef);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool is_pef_file(linput_t *li)
|
||||
{
|
||||
const char *proc = get_pef_processor(li);
|
||||
return proc != NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static char *get_string(
|
||||
linput_t *li,
|
||||
qoff64_t snames_table,
|
||||
int32 off,
|
||||
char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
if ( ssize_t(bufsize) <= 0 )
|
||||
return NULL;
|
||||
|
||||
if ( off == -1 )
|
||||
{
|
||||
buf[0] = '\0';
|
||||
return NULL;
|
||||
}
|
||||
qlseek(li, snames_table+off);
|
||||
lread(li, buf, bufsize);
|
||||
buf[bufsize-1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline const char *get_impsym_name(
|
||||
const char *stable,
|
||||
const void *end,
|
||||
const uint32 *impsym,
|
||||
int i)
|
||||
{
|
||||
size_t off = mflong(impsym[i]) & 0xFFFFFF;
|
||||
if ( stable + off >= end )
|
||||
return NULL;
|
||||
return stable + off;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline size_t get_expsym_name_length(const uint32 *keytable, int i)
|
||||
{
|
||||
return mflong(keytable[i]) >> 16;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool get_expsym_name(
|
||||
const char *stable,
|
||||
const uint32 *keytable,
|
||||
const pef_export_t *pe,
|
||||
int i,
|
||||
const void *end,
|
||||
char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
pe += i;
|
||||
size_t off = (pe->classAndName & 0xFFFFFFL);
|
||||
size_t len = get_expsym_name_length(keytable, i);
|
||||
if ( len >= bufsize )
|
||||
len = bufsize-1;
|
||||
if ( stable+off+len >= end )
|
||||
return false;
|
||||
memcpy(buf, stable+off, len);
|
||||
buf[len] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// is data pointed by [ptr, end) completely inside vector?
|
||||
static bool inside(const bytevec_t &vec, const void *ptr, size_t nelems, size_t elsize)
|
||||
{
|
||||
if ( !is_mul_ok(nelems, elsize) )
|
||||
return false;
|
||||
|
||||
const uchar *p = (const uchar *)ptr;
|
||||
const uchar *e = p + nelems * elsize;
|
||||
return p >= vec.begin()
|
||||
&& p <= vec.end()
|
||||
&& e >= p
|
||||
&& e <= vec.end();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
struct pef_loader_data_t
|
||||
{
|
||||
pef_loader_t pl;
|
||||
pef_library_t *pil;
|
||||
uint32 *impsym;
|
||||
pef_reloc_header_t *prh;
|
||||
const char *stable;
|
||||
const uint16 *relptr;
|
||||
const uint32 *hash;
|
||||
const uint32 *keytable;
|
||||
pef_export_t *pe;
|
||||
pef_loader_data_t(void) { memset(this, 0, sizeof(*this)); }
|
||||
~pef_loader_data_t(void)
|
||||
{
|
||||
qfree(pil);
|
||||
qfree(prh);
|
||||
qfree(pe);
|
||||
qfree(impsym);
|
||||
}
|
||||
};
|
||||
|
||||
enum elderr_t
|
||||
{
|
||||
ELDERR_OK, // loader data ok
|
||||
ELDERR_SHORT, // too short (not enough data even for the header)
|
||||
ELDERR_IMPLIBS, // wrong imported library info
|
||||
ELDERR_IMPSYMS, // wrong imported symbols
|
||||
ELDERR_RELHDRS, // wrong relocation headers
|
||||
ELDERR_STABLE, // wrong symbol table
|
||||
ELDERR_RELOCS, // wrong relocation instructions
|
||||
ELDERR_KEYTABLE, // wrong keytable
|
||||
ELDERR_EXPSYMS, // wrong exported symbols
|
||||
ELDERR_VECTORS, // wrong term/init/main vectors
|
||||
ELDERR_LAST,
|
||||
};
|
||||
|
||||
static elderr_t extract_loader_data(
|
||||
pef_loader_data_t *pd,
|
||||
const bytevec_t &ldrdata,
|
||||
const qvector<pef_section_t> &sec)
|
||||
{
|
||||
if ( ldrdata.size() < sizeof(pef_loader_t) )
|
||||
return ELDERR_SHORT;
|
||||
pd->pl = *(pef_loader_t *)ldrdata.begin();
|
||||
pef_loader_t &pl = pd->pl;
|
||||
swap_pef_loader(pl);
|
||||
const pef_library_t *pil = (pef_library_t *)(ldrdata.begin() + sizeof(pl));
|
||||
const uint32 *impsym = (uint32 *)(pil + pl.importLibraryCount);
|
||||
const pef_reloc_header_t *prh =
|
||||
(pef_reloc_header_t *)(impsym + pl.totalImportedSymbolCount);
|
||||
const char *stable = (char *)(ldrdata.begin() + pl.loaderStringsOffset);
|
||||
const uint16 *relptr = (uint16 *)(ldrdata.begin() + pl.relocInstrOffset);
|
||||
const uint32 *hash = (uint32 *)(ldrdata.begin() + pl.exportHashOffset);
|
||||
const uint32 hashsize = (1 << pl.exportHashTablePower);
|
||||
const uint32 *keytable = hash + hashsize;
|
||||
const pef_export_t *pe = (pef_export_t *)(keytable + pl.exportedSymbolCount);
|
||||
|
||||
if ( !inside(ldrdata, pil, pl.importLibraryCount, sizeof(*pil)) )
|
||||
return ELDERR_IMPLIBS;
|
||||
if ( !inside(ldrdata, impsym, pl.totalImportedSymbolCount, sizeof(*impsym)) )
|
||||
return ELDERR_IMPSYMS;
|
||||
if ( !inside(ldrdata, prh, pl.relocSectionCount, sizeof(*prh)) )
|
||||
return ELDERR_RELHDRS;
|
||||
if ( !inside(ldrdata, stable, 0, 0) )
|
||||
return ELDERR_STABLE;
|
||||
if ( !inside(ldrdata, relptr, 0, 0) )
|
||||
return ELDERR_RELOCS;
|
||||
if ( !inside(ldrdata, pe, pl.exportedSymbolCount, sizeof(*pe)) )
|
||||
return ELDERR_EXPSYMS;
|
||||
if ( !inside(ldrdata, keytable, pl.exportedSymbolCount, sizeof(*keytable)) )
|
||||
return ELDERR_KEYTABLE;
|
||||
// x < -1 || x >= nsecs => unsigned(x+1) > nsecs
|
||||
size_t nsecs = sec.size();
|
||||
if ( pl.termSection+1 > nsecs
|
||||
|| pl.initSection+1 > nsecs
|
||||
|| pl.mainSection+1 > nsecs )
|
||||
{
|
||||
return ELDERR_VECTORS;
|
||||
}
|
||||
{ // malicious input file may have overlapping structures that may
|
||||
// lead too all kinds of problems when we swap their contents.
|
||||
// we simply make a copy and modify copies to ensure that there is
|
||||
// no interference between different structures.
|
||||
pd->pil = qalloc_array<pef_library_t>(pl.importLibraryCount);
|
||||
memmove(pd->pil, pil, pl.importLibraryCount*sizeof(*pil));
|
||||
pd->prh = qalloc_array<pef_reloc_header_t>(pl.relocSectionCount);
|
||||
memmove(pd->prh, prh, pl.relocSectionCount*sizeof(*prh));
|
||||
pd->pe = qalloc_array<pef_export_t>(pl.exportedSymbolCount);
|
||||
memmove(pd->pe, pe, pl.exportedSymbolCount*sizeof(*pe));
|
||||
pd->impsym = qalloc_array<uint32>(pl.totalImportedSymbolCount);
|
||||
memmove(pd->impsym, impsym, pl.totalImportedSymbolCount*sizeof(*impsym));
|
||||
}
|
||||
#if !__MF__
|
||||
for ( int i=0; i < pl.importLibraryCount; i++ )
|
||||
swap_pef_library(pd->pil[i]);
|
||||
for ( int i=0; i < pl.relocSectionCount; i++ )
|
||||
swap_pef_reloc_header(pd->prh[i]);
|
||||
for ( int i=0; i < pl.exportedSymbolCount; i++ )
|
||||
swap_pef_export(pd->pe[i]);
|
||||
#endif
|
||||
pd->stable = stable;
|
||||
pd->relptr = relptr;
|
||||
pd->hash = hash;
|
||||
pd->keytable = keytable;
|
||||
return ELDERR_OK;
|
||||
}
|
||||
16
idasdk76/ldr/pef/makefile
Normal file
16
idasdk76/ldr/pef/makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
PROC=pef
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)pef$(O) : $(I)../ldr/coff/dbxstcla.h $(I)../ldr/coff/storclas.h \
|
||||
$(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../../module/ppc/notify_codes.hpp ../coff/syms.h \
|
||||
../idaldr.h common.cpp pef.cpp pef.hpp
|
||||
766
idasdk76/ldr/pef/pef.cpp
Normal file
766
idasdk76/ldr/pef/pef.cpp
Normal file
@@ -0,0 +1,766 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
* PEF Loader
|
||||
* ----------
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include <typeinf.hpp>
|
||||
#include "pef.hpp"
|
||||
#include "../coff/syms.h"
|
||||
#include "../../module/ppc/notify_codes.hpp"
|
||||
#include "common.cpp"
|
||||
|
||||
static ea_t toc_ea;
|
||||
static netnode toc;
|
||||
//----------------------------------------------------------------------
|
||||
static const char *get_sec_share_name(uint8 share, char *buf, size_t bufsize)
|
||||
{
|
||||
switch ( share )
|
||||
{
|
||||
case PEF_SH_PROCESS: return "Shared within process";
|
||||
case PEF_SH_GLOBAL : return "Shared between all processes";
|
||||
case PEF_SH_PROTECT: return "Shared between all processes but protected";
|
||||
default:
|
||||
qsnprintf(buf, bufsize, "Unknown code %d", share);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_vector(uint32 ea, const char *name)
|
||||
{
|
||||
op_plain_offset(ea, 0, 0);
|
||||
op_plain_offset(ea+4, 0, 0);
|
||||
uint32 mintoc = get_dword(ea+4);
|
||||
if ( segtype(mintoc) == SEG_DATA && mintoc < toc_ea )
|
||||
{
|
||||
toc_ea = mintoc;
|
||||
ppc_module_t::set_toc(toc_ea);
|
||||
}
|
||||
set_name(ea, name, SN_IDBENC);
|
||||
char buf[MAXSTR];
|
||||
qsnprintf(buf, sizeof(buf), ".%s", name);
|
||||
uint32 code = get_dword(ea);
|
||||
add_entry(code, code, buf, true, AEF_IDBENC);
|
||||
make_name_auto(code);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_symbol_class(uint32 ea, uchar sclass, const char *name)
|
||||
{
|
||||
switch ( sclass )
|
||||
{
|
||||
case kPEFCodeSymbol:
|
||||
case kPEFGlueSymbol:
|
||||
add_entry(ea, ea, name, true, AEF_IDBENC);
|
||||
break;
|
||||
case kPEFTVectSymbol:
|
||||
process_vector(ea, name);
|
||||
break;
|
||||
case kPEFTOCSymbol:
|
||||
if ( segtype(ea) == SEG_DATA && ea < toc_ea )
|
||||
{
|
||||
toc_ea = ea;
|
||||
ppc_module_t::set_toc(toc_ea);
|
||||
}
|
||||
toc.charset_ea(ea, XMC_TD+1, 1);
|
||||
/* fall thru */
|
||||
case kPEFDataSymbol:
|
||||
set_name(ea, name, SN_IDBENC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void fixup(uint32 ea, uint32 delta, int extdef)
|
||||
{
|
||||
fixup_data_t fd(FIXUP_OFF32);
|
||||
if ( extdef )
|
||||
fd.set_extdef();
|
||||
segment_t *s = getseg(delta);
|
||||
fd.displacement = get_dword(ea);
|
||||
if ( s == NULL )
|
||||
{
|
||||
fd.off = delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
fd.sel = s->sel;
|
||||
fd.off = delta - get_segm_base(s);
|
||||
}
|
||||
fd.set(ea);
|
||||
uint32 target = get_dword(ea) + delta;
|
||||
put_dword(ea, target);
|
||||
op_plain_offset(ea, 0, 0);
|
||||
//cmd.ea = ea; ua_add_dref(0, target, dr_O); cmd.ea = BADADDR;
|
||||
if ( target != toc_ea
|
||||
&& !has_name(get_flags(ea))
|
||||
&& has_name(get_flags(target)) )
|
||||
{
|
||||
qstring buf;
|
||||
if ( get_name(&buf, target) > 0 )
|
||||
{
|
||||
buf.insert("TC_");
|
||||
force_name(ea, buf.begin());
|
||||
make_name_auto(ea);
|
||||
}
|
||||
}
|
||||
// toc.charset_ea(ea, XMC_TC+1, 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static NORETURN void bad_loader_data(void)
|
||||
{
|
||||
loader_failure("Bad loader data");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static NORETURN void bad_reloc_data(void)
|
||||
{
|
||||
loader_failure("Bad relocation info");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool good_string(const char *begin, const uchar *end, const char *p)
|
||||
{
|
||||
if ( p >= begin )
|
||||
{
|
||||
while ( p < (const char *)end )
|
||||
{
|
||||
if ( *p == '\0' )
|
||||
return true;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_loader_data(bytevec_t &ldrdata, const qvector<pef_section_t> &sec)
|
||||
{
|
||||
pef_loader_data_t pd;
|
||||
elderr_t errcode = extract_loader_data(&pd, ldrdata, sec);
|
||||
if ( errcode != ELDERR_OK )
|
||||
bad_loader_data();
|
||||
|
||||
pef_loader_t &pl = pd.pl;
|
||||
if ( pl.totalImportedSymbolCount != 0 )
|
||||
{
|
||||
uint32 size = pl.totalImportedSymbolCount*4;
|
||||
ea_t undef = free_chunk(inf_get_max_ea(), size, -0xF);
|
||||
ea_t end = undef + size;
|
||||
set_selector(sec.size()+1, 0);
|
||||
if ( !add_segm(sec.size()+1, undef, end, "IMPORT", "XTRN") )
|
||||
loader_failure();
|
||||
|
||||
for ( int i=0; i < pl.importLibraryCount; i++ )
|
||||
{
|
||||
const pef_library_t &pil = pd.pil[i];
|
||||
ea_t ea = undef + 4 * pil.firstImportedSymbol;
|
||||
const char *libname = pd.stable + pil.nameOffset;
|
||||
if ( !good_string(pd.stable, ldrdata.end(), libname) )
|
||||
bad_loader_data();
|
||||
add_extra_cmt(ea, true, "Imports from library %s", libname);
|
||||
if ( (pil.options & PEF_LIB_WEAK) != 0 )
|
||||
add_extra_cmt(ea, true, "Library is weak");
|
||||
}
|
||||
|
||||
inf_set_specsegs(inf_is_64bit() ? 8 : 4);
|
||||
for ( int i=0; i < pl.totalImportedSymbolCount; i++ )
|
||||
{
|
||||
uint32 sym = mflong(pd.impsym[i]);
|
||||
uchar sclass = uchar(sym >> 24);
|
||||
ea_t ea = undef + 4*i;
|
||||
const char *iname = get_impsym_name(pd.stable, ldrdata.end(), pd.impsym, i);
|
||||
if ( iname == NULL )
|
||||
bad_loader_data();
|
||||
set_name(ea, iname, SN_IDBENC);
|
||||
if ( (sclass & kPEFWeak) != 0 )
|
||||
make_name_weak(ea);
|
||||
create_dword(ea, 4);
|
||||
put_dword(ea, 0);
|
||||
pd.impsym[i] = (uint32)ea;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pl.mainSection != -1 )
|
||||
{
|
||||
uint32 ea = sec[pl.mainSection].defaultAddress + pl.mainOffset;
|
||||
toc_ea = sec[1].defaultAddress + get_dword(ea+4);
|
||||
ppc_module_t::set_toc(toc_ea);
|
||||
}
|
||||
else if ( pl.initSection != -1 )
|
||||
{
|
||||
uint32 ea = sec[pl.initSection].defaultAddress + pl.initOffset;
|
||||
toc_ea = sec[1].defaultAddress + get_dword(ea+4);
|
||||
ppc_module_t::set_toc(toc_ea);
|
||||
}
|
||||
|
||||
if ( qgetenv("IDA_NORELOC") )
|
||||
goto EXPORTS;
|
||||
|
||||
msg("Processing relocation information... ");
|
||||
for ( int i=0; i < pl.relocSectionCount; i++ )
|
||||
{
|
||||
const pef_reloc_header_t &prh = pd.prh[i];
|
||||
int sidx = prh.sectionIndex;
|
||||
if ( sidx >= sec.size() )
|
||||
bad_reloc_data();
|
||||
uint32 sea = sec[sidx].defaultAddress;
|
||||
const uint16 *ptr = pd.relptr + prh.firstRelocOffset;
|
||||
if ( !inside(ldrdata, ptr, prh.relocCount, sizeof(*ptr)) )
|
||||
bad_reloc_data();
|
||||
uint32 reladdr = sea;
|
||||
uint32 import = 0;
|
||||
uint32 code = sec.size() > 0 ? sec[0].defaultAddress : 0;
|
||||
uint32 data = sec.size() > 1 ? sec[1].defaultAddress : 0;
|
||||
int32 repeat = -1;
|
||||
for ( int j=0; j < prh.relocCount; )
|
||||
{
|
||||
uint16 insn = mfshort(ptr[j++]);
|
||||
uint16 cnt = insn & 0x1FF;
|
||||
switch ( insn >> 9 )
|
||||
{
|
||||
default: // kPEFRelocBySectDWithSkip= 0x00,/* binary: 00xxxxx */
|
||||
if ( (insn & 0xC000) == 0 )
|
||||
{
|
||||
int skipCount = (insn >> 6) & 0xFF;
|
||||
int relocCount = insn & 0x3F;
|
||||
reladdr += skipCount * 4;
|
||||
while ( relocCount > 0 )
|
||||
{
|
||||
relocCount--;
|
||||
fixup(reladdr, data, 0);
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
bad_reloc_data();
|
||||
|
||||
case kPEFRelocBySectC: // = 0x20, /* binary: 0100000 */
|
||||
cnt++;
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
fixup(reladdr, code, 0);
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
case kPEFRelocBySectD:
|
||||
cnt++;
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
fixup(reladdr, data, 0);
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
case kPEFRelocTVector12:
|
||||
cnt++;
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
fixup(reladdr, code, 0);
|
||||
reladdr += 4;
|
||||
fixup(reladdr, data, 0);
|
||||
reladdr += 4;
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
case kPEFRelocTVector8:
|
||||
cnt++;
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
fixup(reladdr, code, 0);
|
||||
reladdr += 4;
|
||||
fixup(reladdr, data, 0);
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
case kPEFRelocVTable8:
|
||||
cnt++;
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
fixup(reladdr, data, 0);
|
||||
reladdr += 4;
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
case kPEFRelocImportRun:
|
||||
cnt++;
|
||||
if ( import+cnt > pl.totalImportedSymbolCount )
|
||||
bad_reloc_data();
|
||||
while ( cnt > 0 )
|
||||
{
|
||||
cnt--;
|
||||
fixup(reladdr, pd.impsym[import], 1);
|
||||
import++;
|
||||
reladdr += 4;
|
||||
}
|
||||
break;
|
||||
case kPEFRelocSmByImport:
|
||||
if ( cnt >= pl.totalImportedSymbolCount )
|
||||
bad_reloc_data();
|
||||
fixup(reladdr, pd.impsym[cnt], 1);
|
||||
reladdr += 4;
|
||||
import = cnt + 1;
|
||||
break;
|
||||
case kPEFRelocSmSetSectC:
|
||||
if ( cnt >= sec.size() )
|
||||
bad_reloc_data();
|
||||
code = sec[cnt].defaultAddress;
|
||||
break;
|
||||
case kPEFRelocSmSetSectD:
|
||||
if ( cnt >= sec.size() )
|
||||
bad_reloc_data();
|
||||
data = sec[cnt].defaultAddress;
|
||||
break;
|
||||
case kPEFRelocSmBySection:
|
||||
if ( cnt >= sec.size() )
|
||||
bad_reloc_data();
|
||||
fixup(reladdr, sec[cnt].defaultAddress, 0);
|
||||
reladdr += 4;
|
||||
break;
|
||||
|
||||
case kPEFRelocIncrPosition: /* binary: 1000xxx */
|
||||
case kPEFRelocIncrPosition+1:
|
||||
case kPEFRelocIncrPosition+2:
|
||||
case kPEFRelocIncrPosition+3:
|
||||
case kPEFRelocIncrPosition+4:
|
||||
case kPEFRelocIncrPosition+5:
|
||||
case kPEFRelocIncrPosition+6:
|
||||
case kPEFRelocIncrPosition+7:
|
||||
reladdr += (insn & 0x0FFF)+1;
|
||||
break;
|
||||
|
||||
case kPEFRelocSmRepeat: /* binary: 1001xxx */
|
||||
case kPEFRelocSmRepeat+1:
|
||||
case kPEFRelocSmRepeat+2:
|
||||
case kPEFRelocSmRepeat+3:
|
||||
case kPEFRelocSmRepeat+4:
|
||||
case kPEFRelocSmRepeat+5:
|
||||
case kPEFRelocSmRepeat+6:
|
||||
case kPEFRelocSmRepeat+7:
|
||||
if ( repeat == -1 )
|
||||
repeat = (insn & 0xFF)+1;
|
||||
repeat--;
|
||||
if ( repeat != -1 )
|
||||
j -= ((insn>>8) & 15)+1 + 1;
|
||||
break;
|
||||
|
||||
case kPEFRelocSetPosition: /* binary: 101000x */
|
||||
case kPEFRelocSetPosition+1:
|
||||
{
|
||||
ushort next = mfshort(ptr[j++]);
|
||||
uint32 offset = next | (uint32(insn & 0x3FF) << 16);
|
||||
reladdr = sea + offset;
|
||||
}
|
||||
break;
|
||||
|
||||
case kPEFRelocLgByImport: /* binary: 101001x */
|
||||
case kPEFRelocLgByImport+1:
|
||||
{
|
||||
ushort next = mfshort(ptr[j++]);
|
||||
uint32 index = next | (uint32(insn & 0x3FF) << 16);
|
||||
if ( index >= pl.totalImportedSymbolCount )
|
||||
bad_reloc_data();
|
||||
fixup(reladdr, pd.impsym[index], 1);
|
||||
reladdr += 4;
|
||||
import = index + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case kPEFRelocLgRepeat: /* binary: 101100x */
|
||||
case kPEFRelocLgRepeat+1:
|
||||
{
|
||||
ushort next = mfshort(ptr[j++]);
|
||||
if ( repeat == -1 )
|
||||
repeat = next | (uint32(insn & 0x3F) << 16);
|
||||
repeat--;
|
||||
if ( repeat != -1 )
|
||||
j -= ((insn >> 6) & 15) + 1 + 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case kPEFRelocLgSetOrBySection: /* binary: 101101x */
|
||||
case kPEFRelocLgSetOrBySection+1:
|
||||
{
|
||||
ushort next = mfshort(ptr[j++]);
|
||||
uint32 index = next | (uint32(insn & 0x3F) << 16);
|
||||
if ( index >= sec.size() )
|
||||
bad_reloc_data();
|
||||
int subcode = (insn >> 6) & 15;
|
||||
switch ( subcode )
|
||||
{
|
||||
case 0:
|
||||
fixup(reladdr, sec[index].defaultAddress, 0);
|
||||
reladdr += 4;
|
||||
break;
|
||||
case 1:
|
||||
code = sec[index].defaultAddress;
|
||||
break;
|
||||
case 2:
|
||||
data = sec[index].defaultAddress;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPORTS:
|
||||
for ( int i=0; i < pl.exportedSymbolCount; i++ )
|
||||
{
|
||||
const pef_export_t &pe = pd.pe[i];
|
||||
uchar sclass = uchar(pe.classAndName >> 24);
|
||||
char name[MAXSTR];
|
||||
uint32 ea;
|
||||
switch ( pe.sectionIndex )
|
||||
{
|
||||
case -3:
|
||||
{
|
||||
uint symidx = pe.symbolValue;
|
||||
if ( symidx >= pl.totalImportedSymbolCount )
|
||||
bad_reloc_data();
|
||||
ea = pd.impsym[symidx];
|
||||
}
|
||||
break;
|
||||
case -2: // absolute symbol
|
||||
ask_for_feedback("Absolute symbols are not implemented");
|
||||
continue;
|
||||
default:
|
||||
{
|
||||
uint secidx = pe.sectionIndex;
|
||||
if ( secidx >= sec.size() )
|
||||
bad_reloc_data();
|
||||
ea = sec[secidx].defaultAddress + pe.symbolValue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( !get_expsym_name(pd.stable, pd.keytable, pd.pe, i, ldrdata.end(), name, sizeof(name)) )
|
||||
bad_loader_data();
|
||||
process_symbol_class(ea, sclass & 0xF, name);
|
||||
}
|
||||
msg("done.\n");
|
||||
|
||||
if ( pl.mainSection >= 0 && pl.mainSection < sec.size() )
|
||||
{
|
||||
uint32 ea = sec[pl.mainSection].defaultAddress + pl.mainOffset;
|
||||
process_vector(ea, "start");
|
||||
inf_set_start_cs(0);
|
||||
inf_set_start_ip(get_dword(ea));
|
||||
}
|
||||
if ( pl.initSection >= 0 && pl.initSection < sec.size() )
|
||||
{
|
||||
uint32 ea = sec[pl.initSection].defaultAddress + pl.initOffset;
|
||||
process_vector(ea, "INIT_VECTOR");
|
||||
}
|
||||
if ( pl.termSection >= 0 && pl.termSection < sec.size() )
|
||||
{
|
||||
uint32 ea = sec[pl.termSection].defaultAddress + pl.termOffset;
|
||||
process_vector(ea, "TERM_VECTOR");
|
||||
}
|
||||
|
||||
if ( toc_ea != BADADDR )
|
||||
set_name(toc_ea, "TOC");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static NORETURN void bad_packed_data(void)
|
||||
{
|
||||
loader_failure("Illegal compressed data");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static uint32 read_number(const uchar *&packed, const uchar *end)
|
||||
{
|
||||
uint32 arg = 0;
|
||||
for ( int i=0; ; i++ )
|
||||
{
|
||||
if ( packed >= end )
|
||||
bad_packed_data();
|
||||
uchar b = *packed++;
|
||||
arg <<= 7;
|
||||
arg |= (b & 0x7F);
|
||||
if ( (b & 0x80) == 0 )
|
||||
break;
|
||||
if ( i > 4 )
|
||||
bad_packed_data();
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void unpack_section(
|
||||
const bytevec_t &packedvec,
|
||||
ea_t start,
|
||||
uint32 usize)
|
||||
{
|
||||
bytevec_t unpacked;
|
||||
const uchar *packed = packedvec.begin();
|
||||
const uchar *pckend = packedvec.begin() + packedvec.size();
|
||||
while ( packed < pckend )
|
||||
{
|
||||
uchar code = *packed++;
|
||||
uint32 arg = code & 0x1F;
|
||||
if ( arg == 0 )
|
||||
arg = read_number(packed, pckend);
|
||||
switch ( code >> 5 )
|
||||
{
|
||||
case 0: // Zero
|
||||
unpacked.growfill(arg);
|
||||
break;
|
||||
|
||||
case 1: // blockCopy
|
||||
{
|
||||
const uchar *end = packed + arg;
|
||||
if ( end < packed || end > pckend )
|
||||
bad_packed_data();
|
||||
unpacked.append(packed, arg);
|
||||
packed += arg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // repeatedBlock
|
||||
{
|
||||
int32 repeat = read_number(packed, pckend) + 1;
|
||||
const uchar *end = packed + arg;
|
||||
if ( end < packed || end > pckend )
|
||||
bad_packed_data();
|
||||
while ( --repeat >= 0 )
|
||||
unpacked.append(packed, arg);
|
||||
packed += arg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // interleaveRepeatBlockWithBlockCopy
|
||||
{
|
||||
int32 commonSize = arg;
|
||||
int32 customSize = read_number(packed, pckend);
|
||||
int32 repeatCount = read_number(packed, pckend);
|
||||
const uchar *common = packed;
|
||||
packed += commonSize;
|
||||
if ( packed < common || packed > pckend )
|
||||
bad_packed_data();
|
||||
while ( --repeatCount >= 0 )
|
||||
{
|
||||
const uchar *end = packed + customSize;
|
||||
if ( end < packed || end > pckend )
|
||||
bad_packed_data();
|
||||
unpacked.append(common, commonSize);
|
||||
unpacked.append(packed, customSize);
|
||||
packed += customSize;
|
||||
}
|
||||
unpacked.append(common, commonSize);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: // interleaveRepeatBlockWithZero
|
||||
{
|
||||
int32 commonSize = arg;
|
||||
int32 customSize = read_number(packed, pckend);
|
||||
int32 repeatCount = read_number(packed, pckend);
|
||||
while ( --repeatCount >= 0 )
|
||||
{
|
||||
const uchar *end = packed + customSize;
|
||||
if ( end < packed || end > pckend )
|
||||
bad_packed_data();
|
||||
unpacked.growfill(commonSize);
|
||||
unpacked.append(packed, customSize);
|
||||
packed += customSize;
|
||||
}
|
||||
unpacked.growfill(commonSize);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
bad_packed_data();
|
||||
}
|
||||
}
|
||||
if ( unpacked.size() < usize )
|
||||
unpacked.growfill(usize-unpacked.size());
|
||||
if ( unpacked.size() != usize )
|
||||
bad_packed_data();
|
||||
mem2base(unpacked.begin(), start, start+unpacked.size(), FILEREG_NOTPATCHABLE);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_section(
|
||||
int i,
|
||||
linput_t *li,
|
||||
pef_section_t &ps,
|
||||
const char *sname,
|
||||
const char *classname,
|
||||
int is_packed)
|
||||
{
|
||||
uint32 size = ps.totalSize;
|
||||
ea_t base = ps.defaultAddress ? ps.defaultAddress : to_ea(inf_get_baseaddr(), 0);
|
||||
ea_t start = free_chunk(base, size, 1-(1 << ps.alignment));
|
||||
ea_t end = start + size;
|
||||
if ( is_packed )
|
||||
{
|
||||
bytevec_t packed;
|
||||
packed.resize(ps.packedSize);
|
||||
qlseek(li, ps.containerOffset);
|
||||
lread(li, packed.begin(), packed.size());
|
||||
unpack_section(packed, start, ps.unpackedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
file2base(li, ps.containerOffset,
|
||||
start, start+ps.unpackedSize, FILEREG_PATCHABLE);
|
||||
}
|
||||
set_selector(i+1, 0);
|
||||
if ( !add_segm(i+1, start, end, sname, classname, ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
ps.defaultAddress = start;
|
||||
if ( start < inf_get_lowoff() )
|
||||
inf_set_lowoff(start);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
pef_t pef;
|
||||
toc_ea = BADADDR;
|
||||
toc.create("$ toc");
|
||||
qlseek(li, 0);
|
||||
lread(li, &pef, sizeof(pef_t));
|
||||
swap_pef(pef);
|
||||
|
||||
const char *proc = get_pef_processor(pef);
|
||||
if ( proc != NULL )
|
||||
{
|
||||
set_processor_type(proc, SETPROC_LOADER);
|
||||
if ( PH.id == PLFM_PPC )
|
||||
{
|
||||
// Mac OS Runtime Architecture for the PowerPC is very similar to AIX
|
||||
set_abi_name("aix");
|
||||
}
|
||||
}
|
||||
|
||||
// read section headers
|
||||
qvector<pef_section_t> sec;
|
||||
if ( pef.sectionCount != 0 )
|
||||
{
|
||||
sec.resize(pef.sectionCount);
|
||||
lread(li, sec.begin(), sec.size()*sizeof(pef_section_t));
|
||||
}
|
||||
|
||||
// swap section headers and find the loader section
|
||||
pef_section_t *loader = NULL;
|
||||
for ( int i=0; i < sec.size(); i++ )
|
||||
{
|
||||
swap_pef_section(sec[i]);
|
||||
if ( sec[i].sectionKind == PEF_SEC_LOADER )
|
||||
loader = &sec[i];
|
||||
}
|
||||
|
||||
int32 snames_table = sizeof(pef_t) + sizeof(pef_section_t)*sec.size();
|
||||
for ( int i=0; i < sec.size(); i++ )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
char *secname = get_string(li, snames_table, sec[i].nameOffset, buf, sizeof(buf));
|
||||
switch ( sec[i].sectionKind )
|
||||
{
|
||||
case PEF_SEC_PDATA : // Pattern initialized data segment
|
||||
load_section(i, li, sec[i], secname, CLASS_DATA, 1);
|
||||
break;
|
||||
case PEF_SEC_CODE : // Code segment
|
||||
case PEF_SEC_EDATA : // Executable data segment
|
||||
load_section(i, li, sec[i], secname, CLASS_CODE, 0);
|
||||
break;
|
||||
case PEF_SEC_DATA: // Unpacked data segment
|
||||
load_section(i, li, sec[i], secname,
|
||||
sec[i].unpackedSize != 0 ? CLASS_DATA : CLASS_BSS, 0);
|
||||
break;
|
||||
case PEF_SEC_CONST: // Read only data
|
||||
load_section(i, li, sec[i], secname, CLASS_CONST, 0);
|
||||
break;
|
||||
case PEF_SEC_LOADER: // Loader section
|
||||
case PEF_SEC_DEBUG : // Reserved for future use
|
||||
case PEF_SEC_EXCEPT: // Reserved for future use
|
||||
case PEF_SEC_TRACEB: // Reserved for future use
|
||||
continue;
|
||||
default:
|
||||
ask_for_feedback("Unknown section type");
|
||||
continue;
|
||||
}
|
||||
if ( i == 0 )
|
||||
create_filename_cmt();
|
||||
add_extra_cmt(sec[i].defaultAddress, true, "Segment share type: %s\n",
|
||||
get_sec_share_name(sec[i].shareKind, buf, sizeof(buf)));
|
||||
}
|
||||
if ( loader != NULL )
|
||||
{
|
||||
bytevec_t ldrdata;
|
||||
ldrdata.resize(loader->packedSize);
|
||||
qlseek(li, loader->containerOffset);
|
||||
lread(li, ldrdata.begin(), ldrdata.size());
|
||||
process_loader_data(ldrdata, sec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// check input file format. if recognized, then return 1
|
||||
// and fill 'fileformatname'.
|
||||
// otherwise return 0
|
||||
//
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
const char *proc = get_pef_processor(li);
|
||||
if ( proc == NULL )
|
||||
return 0;
|
||||
|
||||
*fileformatname = "PEF (Mac OS or Be OS executable)";
|
||||
*processor = proc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// LOADER DESCRIPTION BLOCK
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
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,
|
||||
};
|
||||
184
idasdk76/ldr/pef/pef.hpp
Normal file
184
idasdk76/ldr/pef/pef.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// PEF file format (Mac OS, Be OS)
|
||||
//
|
||||
|
||||
#ifndef PEF_HPP
|
||||
#define PEF_HPP
|
||||
#pragma pack(push, 1)
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#if __MF__
|
||||
#define mfshort(x) (x)
|
||||
#define lfshort(x) swap16(x)
|
||||
#define mflong(x) (x)
|
||||
#define lflong(x) swap32(x)
|
||||
#else
|
||||
#define mfshort(x) swap16(x)
|
||||
#define lfshort(x) (x)
|
||||
#define mflong(x) swap32(x)
|
||||
#define lflong(x) (x)
|
||||
#endif
|
||||
|
||||
typedef int16 sint16;
|
||||
typedef int32 sint32;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct pef_t
|
||||
{
|
||||
char tag1[4]; // Designates Apply-defined format
|
||||
#define PEF_TAG_1 "Joy!"
|
||||
|
||||
char tag2[4]; // Type of container
|
||||
#define PEF_TAG_2 "peff"
|
||||
|
||||
char architecture[4]; // Target architecture
|
||||
#define PEF_ARCH_PPC "pwpc"
|
||||
#define PEF_ARCH_68K "m68k"
|
||||
|
||||
uint32 formatVersion; // Version of PEF
|
||||
#define PEF_VERSION 1
|
||||
|
||||
uint32 dateTimeStamp; // Number of seconds from January 1, 1904
|
||||
|
||||
uint32 oldDefVersion;
|
||||
uint32 oldImpVersion;
|
||||
uint32 currentVersion;
|
||||
|
||||
uint16 sectionCount; // Total number of sections
|
||||
uint16 instSectionCount; // Number of instantiated sections
|
||||
|
||||
uint32 reservedA; // Should be 0
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct pef_section_t
|
||||
{
|
||||
sint32 nameOffset; // Offset from the start of the section
|
||||
// name table
|
||||
// No name is -1
|
||||
uint32 defaultAddress; // Preferred address for section
|
||||
uint32 totalSize; // Total size of section in memory
|
||||
uint32 unpackedSize; // Initialized size of section in memory
|
||||
uint32 packedSize; // Size of section in file
|
||||
uint32 containerOffset; // Offset from the beginning of the file
|
||||
uint8 sectionKind; // Type of section:
|
||||
#define PEF_SEC_CODE 0 // Code segment
|
||||
#define PEF_SEC_DATA 1 // Unpacked data segment
|
||||
#define PEF_SEC_PDATA 2 // Pattern initialized data segment
|
||||
#define PEF_SEC_CONST 3 // Read only data
|
||||
#define PEF_SEC_LOADER 4 // Loader section
|
||||
#define PEF_SEC_DEBUG 5 // Reserved for future use
|
||||
#define PEF_SEC_EDATA 6 // Executable data segment
|
||||
#define PEF_SEC_EXCEPT 7 // Reserved for future use
|
||||
#define PEF_SEC_TRACEB 8 // Reserved for future use
|
||||
uint8 shareKind; // Section share properties
|
||||
#define PEF_SH_PROCESS 1 // Shared within process
|
||||
#define PEF_SH_GLOBAL 4 // Shared between all processes
|
||||
#define PEF_SH_PROTECT 5 // Shared between all processes but protected
|
||||
uint8 alignment; // Section alignment as power of 2
|
||||
// (here we have an exponent)
|
||||
uint8 reservedA; // Should be 0
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct pef_loader_t
|
||||
{
|
||||
sint32 mainSection; // Number of section with "main" symbol (-1 - none)
|
||||
uint32 mainOffset; // Offset to "main" symbol
|
||||
sint32 initSection; // Number of section with initialization transition vector (-1 - none)
|
||||
uint32 initOffset; // Offset to initialization transition vector
|
||||
sint32 termSection; // Number of section with termination transition vector (-1 - none)
|
||||
uint32 termOffset; // Offset to termination transition vector
|
||||
uint32 importLibraryCount; // Number of imported libraries
|
||||
uint32 totalImportedSymbolCount;
|
||||
uint32 relocSectionCount;
|
||||
uint32 relocInstrOffset;
|
||||
uint32 loaderStringsOffset;
|
||||
uint32 exportHashOffset;
|
||||
uint32 exportHashTablePower;
|
||||
uint32 exportedSymbolCount;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct pef_library_t // Imported Library
|
||||
{
|
||||
uint32 nameOffset; // Offset from beginning of loader string table
|
||||
uint32 oldImpVersion;
|
||||
uint32 currentVersion;
|
||||
uint32 importedSymbolCount;
|
||||
uint32 firstImportedSymbol;
|
||||
uint8 options;
|
||||
#define PEF_LIB_INIT 0x80 // Non-default init order of library
|
||||
#define PEF_LIB_WEAK 0x40 // Weak library
|
||||
uint8 reservedA;
|
||||
uint16 reservedB;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Imported symbol classes
|
||||
|
||||
#define kPEFCodeSymbol 0 // a code address
|
||||
#define kPEFDataSymbol 1 // a data address
|
||||
#define kPEFTVectSymbol 2 // a standard procedure pointer
|
||||
#define kPEFTOCSymbol 3 // a direct data area (TOC) symbol
|
||||
#define kPEFGlueSymbol 4 // a linker-inserted glue symbol
|
||||
|
||||
#define kPEFWeak 0x80 // Weak symbol mask
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Relocation Header
|
||||
struct pef_reloc_header_t
|
||||
{
|
||||
uint16 sectionIndex;
|
||||
uint16 reservedA;
|
||||
uint32 relocCount;
|
||||
uint32 firstRelocOffset;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Relocation Instructions
|
||||
|
||||
enum
|
||||
{
|
||||
kPEFRelocBySectDWithSkip= 0x00,/* binary: 00xxxxx */
|
||||
|
||||
kPEFRelocBySectC = 0x20, /* binary: 0100000 */
|
||||
kPEFRelocBySectD = 0x21, /* binary: 0100001 */
|
||||
kPEFRelocTVector12 = 0x22, /* binary: 0100010 */
|
||||
kPEFRelocTVector8 = 0x23, /* binary: 0100011 */
|
||||
kPEFRelocVTable8 = 0x24, /* binary: 0100100 */
|
||||
kPEFRelocImportRun = 0x25, /* binary: 0100101 */
|
||||
|
||||
kPEFRelocSmByImport = 0x30, /* binary: 0110000 */
|
||||
kPEFRelocSmSetSectC = 0x31, /* binary: 0110001 */
|
||||
kPEFRelocSmSetSectD = 0x32, /* binary: 0110010 */
|
||||
kPEFRelocSmBySection = 0x33, /* binary: 0110011 */
|
||||
|
||||
kPEFRelocIncrPosition= 0x40, /* binary: 1000xxx */
|
||||
kPEFRelocSmRepeat = 0x48, /* binary: 1001xxx */
|
||||
|
||||
kPEFRelocSetPosition = 0x50, /* binary: 101000x */
|
||||
kPEFRelocLgByImport = 0x52, /* binary: 101001x */
|
||||
kPEFRelocLgRepeat = 0x58, /* binary: 101100x */
|
||||
kPEFRelocLgSetOrBySection= 0x5A,/* binary: 101101x */
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Exported Symbols
|
||||
struct pef_export_t
|
||||
{
|
||||
uint32 classAndName;
|
||||
uint32 symbolValue;
|
||||
sint16 sectionIndex;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // PEF_HPP
|
||||
Reference in New Issue
Block a user