update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

313
idasdk76/ldr/pef/common.cpp Normal file
View 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
View 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
View 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
View 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