update to ida 7.6, add builds
This commit is contained in:
660
idasdk76/ldr/aout/aout.cpp
Normal file
660
idasdk76/ldr/aout/aout.cpp
Normal file
@@ -0,0 +1,660 @@
|
||||
/*
|
||||
* This Loader Module is written by Yury Haron
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
L O A D E R for a.out (Linux)
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
//#define DEBUG
|
||||
#include "aout.h"
|
||||
#include "common.cpp"
|
||||
#include "../../module/sparc/notify_codes.hpp"
|
||||
|
||||
class aout_t
|
||||
{
|
||||
public:
|
||||
exec ex;
|
||||
nlist *symtab;
|
||||
char *strtab;
|
||||
uint32 symcount; // number of symbols in symtab
|
||||
|
||||
uint32 text; // first address of each section
|
||||
uint32 data;
|
||||
uint32 bss;
|
||||
uint32 extrn;
|
||||
uint32 top; // next available address
|
||||
|
||||
uint32 treloff; // file offset of each section
|
||||
uint32 dreloff;
|
||||
uint32 symoff;
|
||||
uint32 stroff;
|
||||
|
||||
bool msb;
|
||||
|
||||
aout_t(void)
|
||||
{
|
||||
memset((void*) this, 0, sizeof(*this));
|
||||
}
|
||||
~aout_t()
|
||||
{
|
||||
if ( symtab != NULL )
|
||||
{
|
||||
qfree(symtab);
|
||||
symtab = NULL;
|
||||
}
|
||||
if ( strtab != NULL )
|
||||
{
|
||||
qfree(strtab);
|
||||
strtab = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *guess_processor(const exec &ex)
|
||||
{
|
||||
if ( N_MACHTYPE(ex) )
|
||||
{
|
||||
switch ( N_MACHTYPE(ex) )
|
||||
{
|
||||
case M_386:
|
||||
case M_386_NETBSD:
|
||||
return "metapc";
|
||||
|
||||
case M_ARM:
|
||||
case M_ARM6_NETBSD:
|
||||
return "arm";
|
||||
|
||||
case M_SPARC:
|
||||
return "sparcb";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *)
|
||||
{
|
||||
exec ex;
|
||||
int i = get_aout_file_format_index(li, &ex);
|
||||
#ifdef DEBUG
|
||||
msg("getfmtindex=%d\n", i);
|
||||
#endif
|
||||
|
||||
if ( i == 0 )
|
||||
return 0;
|
||||
|
||||
static const char *const ff[] =
|
||||
{
|
||||
"demand-paged executable with NULL-ptr check", // q
|
||||
"object or impure executable", // o
|
||||
"demand-paged executable", // z
|
||||
"core", // c
|
||||
"pure executable", // n
|
||||
"OpenBSD demand-paged executable", // zo
|
||||
};
|
||||
fileformatname->sprnt("a.out (%s)", ff[i-1]);
|
||||
*processor = guess_processor(ex);
|
||||
#ifdef DEBUG
|
||||
msg("%s\n", fileformatname.c_str());
|
||||
#endif
|
||||
return f_AOUT;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create32(
|
||||
processor_t &ph,
|
||||
ushort sel,
|
||||
ea_t start_ea,
|
||||
ea_t end_ea,
|
||||
const char *name,
|
||||
const char *classname)
|
||||
{
|
||||
set_selector(sel, 0);
|
||||
if ( !add_segm(sel, start_ea, end_ea, name, classname, ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
if ( ph.id == PLFM_386 )
|
||||
set_segm_addressing(getseg(start_ea), 1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool ana_hdr(processor_t &ph, linput_t *li, exec *_ex)
|
||||
{
|
||||
bool msb = false;
|
||||
exec &ex = *_ex;
|
||||
lread(li, &ex, sizeof(ex));
|
||||
|
||||
if ( N_BADMAG(ex) )
|
||||
{
|
||||
swap_exec(ex);
|
||||
msb = true;
|
||||
msg("Assuming big-endian...\n");
|
||||
}
|
||||
const char *proc = guess_processor(ex);
|
||||
if ( proc != NULL )
|
||||
{
|
||||
set_processor_type(proc, SETPROC_LOADER);
|
||||
if ( N_MACHTYPE(ex) == M_SPARC )
|
||||
sparc_module_t::set_v8(true); // set SPARC_V8 parameter
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ask_yn(ASKBTN_YES,
|
||||
"HIDECANCEL\n"
|
||||
"AUTOHIDE REGISTRY\n"
|
||||
"Missing machine type. Continue?") <= ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
if ( ph.id == -1 )
|
||||
set_processor_type(inf_get_procname().c_str(), SETPROC_LOADER);
|
||||
}
|
||||
return msb;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline fixup_type_t get_hi22_reltype()
|
||||
{
|
||||
static fixup_type_t hi22_reltype = FIXUP_CUSTOM;
|
||||
if ( hi22_reltype == FIXUP_CUSTOM )
|
||||
hi22_reltype = find_custom_fixup("HI22");
|
||||
return hi22_reltype;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline fixup_type_t get_lo10_reltype()
|
||||
{
|
||||
static fixup_type_t lo10_reltype = FIXUP_CUSTOM;
|
||||
if ( lo10_reltype == FIXUP_CUSTOM )
|
||||
lo10_reltype = find_custom_fixup("LO10");
|
||||
return lo10_reltype;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void do_fixup(uint32 where, uint32 delta, uint32 target, fixup_type_t type, int external)
|
||||
{
|
||||
fixup_data_t fd(type);
|
||||
if ( external )
|
||||
fd.set_extdef();
|
||||
|
||||
fd.displacement = delta;
|
||||
if ( external )
|
||||
target -= delta;
|
||||
|
||||
segment_t *s = getseg(target);
|
||||
if ( s != NULL )
|
||||
{
|
||||
fd.sel = s->sel;
|
||||
fd.off = target - get_segm_base(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd.off = target;
|
||||
}
|
||||
fd.set(where);
|
||||
}
|
||||
|
||||
#define S_MASK(x) ((1 << (x)) - 1)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void do_relocation_sparc(
|
||||
linput_t *li,
|
||||
const aout_t &ctx,
|
||||
uint32 off,
|
||||
uint32 len,
|
||||
int seg)
|
||||
{
|
||||
const segment_t *seg_p = getnseg(seg);
|
||||
if ( seg_p == NULL )
|
||||
{
|
||||
msg("relocation data for missing segment %d ignored\n", seg);
|
||||
return;
|
||||
}
|
||||
uint32 base = seg == 1 ? ctx.text : ctx.data;
|
||||
#ifdef DEBUG
|
||||
msg("seg %d base 0x%08X\n", seg, base);
|
||||
#endif
|
||||
|
||||
// load relocation table
|
||||
uint32 relcount = len / sizeof(reloc_info_sparc);
|
||||
validate_array_count(li, &relcount, sizeof(reloc_info_sparc), "Relocation count", off);
|
||||
if ( relcount == 0 )
|
||||
return;
|
||||
reloc_info_sparc *reltab = qalloc_array<reloc_info_sparc>(relcount);
|
||||
if ( reltab == NULL )
|
||||
loader_failure("Unable to allocate relocation table for %u entries\n", relcount);
|
||||
qlseek(li, off);
|
||||
for ( reloc_info_sparc *rel = reltab; rel < reltab + relcount; rel++ )
|
||||
{
|
||||
uint32 temp = 0;
|
||||
lread4bytes(li, &rel->r_address, ctx.msb);
|
||||
lread4bytes(li, &temp, ctx.msb);
|
||||
lread4bytes(li, &rel->r_addend, ctx.msb);
|
||||
rel->r_index = (temp >> 8) & 0x00FFFFFF;
|
||||
rel->r_extern = (temp >> 7) & 1;
|
||||
rel->r_type = (reloc_type_sparc) ((temp) & 0x1F);
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( rel->r_address >= 0x80C8 && rel->r_address <= 0x8200 )
|
||||
msg("%08X: index=0x%06X extern=%d type=%02X addend=0x%08X\n",
|
||||
rel->r_address, rel->r_index, rel->r_extern, rel->r_type, rel->r_addend);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// perform relocation
|
||||
for ( reloc_info_sparc *rel = reltab; rel < reltab + relcount; rel++ )
|
||||
{
|
||||
uint32 where = base + rel->r_address;
|
||||
uint32 instr = get_dword(where);
|
||||
fixup_type_t type = FIXUP_OFF32;
|
||||
uint32 target = where;
|
||||
uint32 value;
|
||||
uint32 merged;
|
||||
#ifdef DEBUG
|
||||
value = instr;
|
||||
merged = instr;
|
||||
#endif
|
||||
|
||||
if ( rel->r_extern )
|
||||
{
|
||||
if ( rel->r_index >= ctx.symcount )
|
||||
{
|
||||
msg("%08X: relocation to extern symbol idx %08X out of bounds, ignored\n", where, rel->r_index);
|
||||
continue;
|
||||
}
|
||||
nlist *sym = &ctx.symtab[rel->r_index];
|
||||
|
||||
// The in-database address for this symbol was set when loading the symtab.
|
||||
target = sym->n_value;
|
||||
target += rel->r_addend;
|
||||
|
||||
/*
|
||||
if ( (sym->n_type & N_TYPE ) != N_ABS &&
|
||||
(sym->n_type & N_TYPE) != N_COMM)
|
||||
target += where;
|
||||
|
||||
if ( (rel->r_type == SPARC_RELOC_PC10 ) ||
|
||||
(rel->r_type == SPARC_RELOC_PC22))
|
||||
target -= where;
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rel->r_type == SPARC_RELOC_HI22 || rel->r_type == SPARC_RELOC_LO10 )
|
||||
target = rel->r_addend;
|
||||
if ( seg == 2 && rel->r_type == SPARC_RELOC_32 )
|
||||
target = rel->r_addend;
|
||||
/*
|
||||
if ( (rel->r_index == N_TEXT ) ||
|
||||
(rel->r_index == N_DATA) ||
|
||||
(rel->r_index == N_BSS))
|
||||
target = rel->r_addend;
|
||||
*/
|
||||
}
|
||||
|
||||
uint32 delta = 0;
|
||||
switch ( rel->r_type )
|
||||
{
|
||||
case SPARC_RELOC_32:
|
||||
value = instr;
|
||||
target += value;
|
||||
merged = target;
|
||||
break;
|
||||
case SPARC_RELOC_WDISP30:
|
||||
value = (instr & S_MASK(30));
|
||||
target += value;
|
||||
merged = (instr & ~S_MASK(30)) | ((target >> 2) & S_MASK(30));
|
||||
break;
|
||||
case SPARC_RELOC_WDISP22:
|
||||
value = (instr & S_MASK(22));
|
||||
target += value;
|
||||
merged = (instr & ~S_MASK(22)) | ((target >> 2) & S_MASK(22));
|
||||
break;
|
||||
case SPARC_RELOC_HI22:
|
||||
value = (instr & S_MASK(22)) << 10;
|
||||
target += value;
|
||||
merged = (instr & ~S_MASK(22)) | ((target >> 10) & S_MASK(22));
|
||||
delta = 0; //-(target & S_MASK(10));
|
||||
type = get_hi22_reltype();
|
||||
break;
|
||||
case SPARC_RELOC_LO10:
|
||||
value = (instr & S_MASK(10));
|
||||
target += value;
|
||||
merged = (instr & ~S_MASK(10)) | ((target) & S_MASK(10));
|
||||
type = get_lo10_reltype();
|
||||
break;
|
||||
default:
|
||||
msg("Unsupported sparc relocation type 0x%02X, ignored\n", rel->r_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// if ( rel->r_address < 0x300 )
|
||||
// msg("%08X: %08X -> %08X (%08X -> %08X)\n", where, instr, merged, value, target);
|
||||
#endif
|
||||
|
||||
put_dword(where, merged);
|
||||
do_fixup(where, rel->r_extern ? rel->r_addend : delta, target, type, rel->r_extern);
|
||||
}
|
||||
|
||||
qfree(reltab);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void do_relocation(linput_t *li, const aout_t &ctx, uint32 off, uint32 len, int seg)
|
||||
{
|
||||
switch ( N_MACHTYPE(ctx.ex) )
|
||||
{
|
||||
case M_SPARC:
|
||||
do_relocation_sparc(li, ctx, off, len, seg);
|
||||
break;
|
||||
default:
|
||||
msg("Warning: Relocation in image file not supported yet for this processor\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void load_syms(linput_t *li, aout_t &ctx)
|
||||
{
|
||||
// get string table length
|
||||
uint32 tabsize = 0;
|
||||
qlseek(li, ctx.stroff);
|
||||
lread4bytes(li, &tabsize, ctx.msb);
|
||||
#ifdef DEBUG
|
||||
msg("symoff=0x%08x symlen=0x%08x stroff=0x%08x strlen=0x%08x\n",
|
||||
ctx.symoff, ctx.ex.a_syms, ctx.stroff, tabsize);
|
||||
#endif
|
||||
|
||||
// load string table
|
||||
char *strtab = (char *)qalloc(tabsize+1);
|
||||
if ( strtab == NULL )
|
||||
loader_failure("Unable to allocate string table for %u bytes\n", tabsize+1);
|
||||
qlseek(li, ctx.stroff);
|
||||
lreadbytes(li, strtab, tabsize, false);
|
||||
strtab[tabsize] = '\0'; // ensure trailing zero
|
||||
|
||||
// load symbol table
|
||||
ctx.symcount = ctx.ex.a_syms / sizeof(nlist);
|
||||
validate_array_count_or_die(li, ctx.symcount, sizeof(nlist),
|
||||
"Number of symbols", ctx.symoff);
|
||||
nlist *symtab = qalloc_array<nlist>(ctx.symcount);
|
||||
if ( symtab == NULL )
|
||||
loader_failure("Unable to allocate symbol table for %u entries\n", ctx.symcount);
|
||||
qlseek(li, ctx.symoff);
|
||||
uint32 extern_count = 0;
|
||||
for ( nlist *sym = symtab; sym < symtab + ctx.symcount; sym++ )
|
||||
{
|
||||
lread4bytes(li, &sym->n_un.n_strx, ctx.msb);
|
||||
lreadbytes(li, &sym->n_type, 1, ctx.msb);
|
||||
lreadbytes(li, &sym->n_other, 1, ctx.msb);
|
||||
lread2bytes(li, &sym->n_desc, ctx.msb);
|
||||
lread4bytes(li, &sym->n_value, ctx.msb);
|
||||
|
||||
if ( sym->n_type == N_EXT )
|
||||
extern_count++;
|
||||
}
|
||||
|
||||
// create extern section
|
||||
uint32 extern_base = ctx.top;
|
||||
if ( extern_count != 0 )
|
||||
{
|
||||
// create new segment
|
||||
add_segm(0, extern_base, extern_base + (extern_count * 4), "extern", "XTRN", ADDSEG_SPARSE);
|
||||
ctx.extrn = extern_base;
|
||||
ctx.top += extern_count * 4;
|
||||
}
|
||||
|
||||
|
||||
// import symbols
|
||||
#ifdef DEBUG
|
||||
int i = 0;
|
||||
#endif
|
||||
uint32 i_extern = 0;
|
||||
for ( nlist *sym = symtab; sym < symtab + ctx.symcount; sym++ )
|
||||
{
|
||||
if ( sym->n_type & N_STAB ) // debug stab info, not a symbol
|
||||
continue;
|
||||
|
||||
if ( sym->n_type == N_EXT )
|
||||
{
|
||||
sym->n_value = extern_base + (i_extern * 4);
|
||||
if ( getseg(sym->n_value) )
|
||||
put_dword(sym->n_value, 0);
|
||||
i_extern++;
|
||||
}
|
||||
|
||||
if ( getseg(sym->n_value) != NULL )
|
||||
{
|
||||
if ( sym->n_un.n_strx < tabsize )
|
||||
{
|
||||
set_name(sym->n_value, strtab + sym->n_un.n_strx,
|
||||
(sym->n_type & N_EXT ? SN_PUBLIC : SN_NON_PUBLIC)|SN_NOCHECK|SN_NOWARN|SN_IDBENC);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg("%08X: type=0x%02X other=0x%02X desc=0x%04X: bad str offset %08X\n",
|
||||
sym->n_value, sym->n_type, sym->n_other, sym->n_desc,
|
||||
sym->n_un.n_strx);
|
||||
}
|
||||
}
|
||||
|
||||
if ( (sym->n_type & N_TYPE) == N_ABS )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
msg("%04X: %08X: type=0x%02X other=0x%02X desc=0x%04X: %s\n",
|
||||
i, sym->n_value, sym->n_type, sym->n_other, sym->n_desc,
|
||||
strtab + sym->n_un.n_strx);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
i++;
|
||||
#endif
|
||||
}
|
||||
|
||||
ctx.strtab = strtab;
|
||||
ctx.symtab = symtab;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void handle_ld_info(linput_t *li, int diroff, int base)
|
||||
{
|
||||
lddir_t lddir;
|
||||
qlseek(li, diroff);
|
||||
lread(li, &lddir, sizeof(lddir));
|
||||
|
||||
ld_info_t ldinfo;
|
||||
qlseek(li, lddir.ldinfo-base);
|
||||
lread(li, &ldinfo, sizeof(ldinfo));
|
||||
|
||||
qoff64_t fpos = ldinfo.symbols - base;
|
||||
int nsyms = (ldinfo.strings - ldinfo.symbols) / sizeof(ld_symbol_t);
|
||||
validate_array_count(li, &nsyms, sizeof(ld_symbol_t), "Symbol count", fpos);
|
||||
qlseek(li, fpos);
|
||||
for ( int i=0; i < nsyms; i++ )
|
||||
{
|
||||
ld_symbol_t sym;
|
||||
lread(li, &sym, sizeof(sym));
|
||||
|
||||
char name[MAXSTR];
|
||||
qlgetz(li, ldinfo.strings + sym.nameoff - base, name, sizeof(name));
|
||||
|
||||
set_name(sym.addr, name, SN_IDBENC);
|
||||
if ( (sym.flags & (AOUT_LD_FUNC|AOUT_LD_DEF)) == AOUT_LD_FUNC )
|
||||
{ // imported function
|
||||
put_byte(sym.addr, 0xC3); // return
|
||||
if ( sym.addr <= ldinfo.ldentry )
|
||||
warning("interr: symbol #%d (%s) is not in the plt", i, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
processor_t &ph = PH;
|
||||
aout_t ctx;
|
||||
exec &ex = ctx.ex;
|
||||
ctx.msb = ana_hdr(ph, li, &ex);
|
||||
ctx.symtab = NULL;
|
||||
ctx.symcount = 0;
|
||||
ctx.strtab = NULL;
|
||||
ctx.treloff = N_TRELOFF(ex);
|
||||
ctx.dreloff = N_DRELOFF(ex);
|
||||
ctx.symoff = N_SYMOFF(ex);
|
||||
ctx.stroff = N_STROFF(ex);
|
||||
|
||||
int txtoff = N_TXTOFF(ex);
|
||||
int txtadr;
|
||||
|
||||
switch ( ph.id )
|
||||
{
|
||||
case PLFM_SPARC:
|
||||
txtoff = N_TXTOFF_SPARC(ex);
|
||||
txtadr = N_TXTADDR_SPARC(ex);
|
||||
ctx.treloff = N_TRELOFF_SPARC(ex);
|
||||
ctx.dreloff = N_DRELOFF_SPARC(ex);
|
||||
ctx.symoff = N_SYMOFF_SPARC(ex);
|
||||
ctx.stroff = N_STROFF_SPARC(ex);
|
||||
break;
|
||||
|
||||
case PLFM_ARM:
|
||||
txtadr = N_TXTADDR_ARM(ex);
|
||||
break;
|
||||
|
||||
default:
|
||||
txtadr = N_TXTADDR(ex);
|
||||
switch ( N_MAGIC(ex) )
|
||||
{
|
||||
// case NMAGIC:
|
||||
// case CMAGIC:
|
||||
default:
|
||||
loader_failure("This image type is not supported yet");
|
||||
|
||||
case ZMAGIC:
|
||||
if ( qlsize(li) < ex.a_text + ex.a_data + N_SYMSIZE(ex) + txtoff )
|
||||
{
|
||||
txtoff = 0;
|
||||
txtadr = 0x1000;
|
||||
}
|
||||
else if ( txtoff < 512 )
|
||||
{
|
||||
loader_failure("Size of demand page < size of block");
|
||||
}
|
||||
// fallthrough
|
||||
case QMAGIC:
|
||||
if ( ex.a_text & 0xFFF || ex.a_data & 0xFFF )
|
||||
loader_failure("Executable is not page aligned");
|
||||
break;
|
||||
|
||||
case OMAGIC:
|
||||
txtoff = sizeof(ex);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
inf_set_baseaddr(0);
|
||||
|
||||
uint32 base, top;
|
||||
top = base = txtadr;
|
||||
if ( ex.a_text || ex.a_data )
|
||||
{
|
||||
top += ex.a_text;
|
||||
// msg("txtoff=%d, base=%d top=%d end=%d\n", txtoff, base, top, top+ex.a_data);
|
||||
file2base(li, txtoff, base, top + ex.a_data, FILEREG_PATCHABLE);
|
||||
if ( ex.a_text )
|
||||
{
|
||||
create32(ph, 1, base, top, NAME_CODE, CLASS_CODE);
|
||||
inf_set_start_cs(1);
|
||||
inf_set_start_ip(ex.a_entry);
|
||||
ctx.text = base;
|
||||
}
|
||||
if ( ex.a_data )
|
||||
{
|
||||
base = top;
|
||||
create32(ph, 2, base, top += ex.a_data, NAME_DATA, CLASS_DATA);
|
||||
set_default_dataseg(2);
|
||||
ctx.data = base;
|
||||
}
|
||||
}
|
||||
if ( ex.a_bss )
|
||||
{
|
||||
create32(ph, 3, top, top + ex.a_bss, NAME_BSS, CLASS_BSS);
|
||||
ctx.bss = top;
|
||||
}
|
||||
ctx.top = top + ex.a_bss;
|
||||
|
||||
if ( ex.a_syms )
|
||||
load_syms(li, ctx);
|
||||
|
||||
if ( N_TRSIZE(ex) )
|
||||
do_relocation(li, ctx, ctx.treloff, N_TRSIZE(ex), 1);
|
||||
if ( N_DRSIZE(ex) )
|
||||
do_relocation(li, ctx, ctx.dreloff, N_DRSIZE(ex), 2);
|
||||
|
||||
// We come in here for the regular a.out style of shared libraries */
|
||||
// ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
|
||||
// return -ENOEXEC;
|
||||
// }
|
||||
// For QMAGIC, the starting address is 0x20 into the page. We mask
|
||||
// this off to get the starting address for the page */
|
||||
// start_addr = ex.a_entry & 0xfffff000;
|
||||
//////
|
||||
|
||||
if ( ph.id != PLFM_SPARC && N_FLAGS(ex) & EX_PIC )
|
||||
handle_ld_info(li, ex.a_text, txtadr);
|
||||
|
||||
create_filename_cmt();
|
||||
add_pgm_cmt("Flag value: %Xh", N_FLAGS(ex));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
283
idasdk76/ldr/aout/aout.h
Normal file
283
idasdk76/ldr/aout/aout.h
Normal file
@@ -0,0 +1,283 @@
|
||||
#ifndef __AOUT_H__
|
||||
#define __AOUT_H__
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct exec
|
||||
{
|
||||
uint32 a_info; // Use macros N_MAGIC, etc for access
|
||||
uint32 a_text; // length of text, in bytes
|
||||
uint32 a_data; // length of data, in bytes
|
||||
uint32 a_bss; // length of bss area for file, in bytes
|
||||
uint32 a_syms; // length of symbol table data in file, in bytes
|
||||
uint32 a_entry; // start address
|
||||
uint32 a_trsize; // length of relocation info for text, in bytes
|
||||
uint32 a_drsize; // length of relocation info for data, in bytes
|
||||
// Added for i960
|
||||
// uint32 a_tload; // Text runtime load adderr
|
||||
// uint32 a_dload; // Data runtime load address
|
||||
// uchar a_talign; // Alignment of text segment
|
||||
// uchar a_dalign; // Alignmrnt of data segment
|
||||
// uchar a_balign; // Alignment of bss segment
|
||||
// char a_relaxable;// Enough info for linker relax
|
||||
};
|
||||
//====================
|
||||
#define N_TRSIZE(a) ((a).a_trsize)
|
||||
#define N_DRSIZE(a) ((a).a_drsize)
|
||||
#define N_SYMSIZE(a) ((a).a_syms)
|
||||
|
||||
#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000ul)
|
||||
|
||||
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
|
||||
#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
|
||||
#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
|
||||
//====================
|
||||
enum machine_type
|
||||
{
|
||||
// M_OLDSUN2 = 0,
|
||||
M_UNKNOWN = 0,
|
||||
M_68010 = 1,
|
||||
M_68020 = 2,
|
||||
M_SPARC = 3,
|
||||
/*-----------------11.07.98 04:09-------------------
|
||||
* skip a bunch so we don't run into any of suns numbers */
|
||||
/*-----------------11.07.98 04:09-------------------
|
||||
* make these up for the ns32k*/
|
||||
M_NS32032 = (64), /* ns32032 running ? */
|
||||
M_NS32532 = (64 + 5), /* ns32532 running mach */
|
||||
M_386 = 100,
|
||||
M_29K = 101, /* AMD 29000 */
|
||||
M_386_DYNIX = 102, /* Sequent running dynix */
|
||||
M_ARM = 103, /* Advanced Risc Machines ARM */
|
||||
M_SPARCLET = 131, /* SPARClet = M_SPARC + 128 */
|
||||
M_386_NETBSD = 134, /* NetBSD/i386 binary */
|
||||
M_68K_NETBSD = 135, /* NetBSD/m68k binary */
|
||||
M_68K4K_NETBSD = 136, /* NetBSD/m68k4k binary */
|
||||
M_532_NETBSD = 137, /* NetBSD/ns32k binary */
|
||||
M_SPARC_NETBSD = 138, /* NetBSD/sparc binary */
|
||||
M_PMAX_NETBSD = 139, /* NetBSD/pmax (MIPS little-endian) binary */
|
||||
M_VAX_NETBSD = 140, /* NetBSD/vax binary */
|
||||
M_ALPHA_NETBSD = 141, /* NetBSD/alpha binary */
|
||||
M_ARM6_NETBSD = 143, /* NetBSD/arm32 binary */
|
||||
M_SPARCLET_1 = 147, /* 0x93, reserved */
|
||||
M_MIPS1 = 151, /* MIPS R2000/R3000 binary */
|
||||
M_MIPS2 = 152, /* MIPS R4000/R6000 binary */
|
||||
M_SPARCLET_2 = 163, /* 0xa3, reserved */
|
||||
M_SPARCLET_3 = 179, /* 0xb3, reserved */
|
||||
M_SPARCLET_4 = 195, /* 0xc3, reserved */
|
||||
M_HP200 = 200, /* HP 200 (68010) BSD binary */
|
||||
M_HP300 = (300 % 256), /* HP 300 (68020+68881) BSD binary */
|
||||
M_HPUX = (0x20c % 256), /* HP 200/300 HPUX binary */
|
||||
M_SPARCLET_5 = 211, /* 0xd3, reserved */
|
||||
M_SPARCLET_6 = 227, /* 0xe3, reserved */
|
||||
M_SPARCLET_7 = 243 /* 0xf3, reserved */
|
||||
};
|
||||
//====================
|
||||
#define OMAGIC 0407 // object file or impure executable
|
||||
#define NMAGIC 0410 // pure executeable
|
||||
#define ZMAGIC 0413 // demand-paged executable
|
||||
#define BMAGIC 0415 // Used by a b.out object
|
||||
#define QMAGIC 0314 // demand-paged executable with the header in the text.
|
||||
// The first page is unmapped to help trap NULL pointer
|
||||
// referenced
|
||||
#define CMAGIC 0421 // core file
|
||||
//====================
|
||||
// Flags:
|
||||
#define EX_PIC 0x80 /* contains position independent code */
|
||||
#define EX_DYNAMIC 0x40 /* contains run-time link-edit info */
|
||||
#define EX_DPMASK 0xC0 /* mask for the above */
|
||||
//====================
|
||||
|
||||
#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
|
||||
&& N_MAGIC(x) != NMAGIC \
|
||||
&& N_MAGIC(x) != ZMAGIC \
|
||||
&& N_MAGIC(x) != QMAGIC)
|
||||
|
||||
#define _N_HDROFF(x) (1024 - sizeof(struct exec))
|
||||
|
||||
#define N_TXTOFF(x) \
|
||||
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
|
||||
(N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
|
||||
|
||||
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
|
||||
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
|
||||
#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x))
|
||||
#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x))
|
||||
#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
|
||||
|
||||
// Address of text segment in memory after it is loaded
|
||||
#define PAGE_SIZE (1UL << 12)
|
||||
#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
|
||||
|
||||
#define PAGE_SIZE_ARM 0x8000UL
|
||||
#define N_TXTADDR_ARM(x) (N_MAGIC(x) == QMAGIC ? 0 : PAGE_SIZE_ARM)
|
||||
|
||||
// Address of data segment in memory after it is loaded. (for linux)
|
||||
/*
|
||||
#define SEGMENT_SIZE 1024
|
||||
#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
|
||||
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
|
||||
#define N_DATADDR(x) \
|
||||
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) : \
|
||||
(_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
|
||||
// Address of bss segment in memory after it is loaded
|
||||
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
|
||||
*/
|
||||
//========================
|
||||
struct nlist
|
||||
{
|
||||
union
|
||||
{
|
||||
int32 n_strx;
|
||||
} n_un;
|
||||
uchar n_type;
|
||||
char n_other;
|
||||
short n_desc;
|
||||
uint32 n_value;
|
||||
};
|
||||
|
||||
#define N_UNDF 0 // Undefined symbol
|
||||
#define N_ABS 2 // Absolute symbol -- addr
|
||||
#define N_TEXT 4 // Text sym -- offset in text segment
|
||||
#define N_DATA 6 // Data sym -- offset in data segment
|
||||
#define N_BSS 8 // BSS sym -- offset in bss segment
|
||||
#define N_COMM 0x12 // Common symbol (visible after shared)
|
||||
#define N_FN 0x1F // File name of .o file
|
||||
#define N_FN_SEQ 0x0C // N_FN from Sequent compilers
|
||||
|
||||
#define N_EXT 1 // External (ORed wits UNDF, ABS, TEXT, DATA or BSS)
|
||||
#define N_TYPE 0x1E
|
||||
#define N_STAB 0xE0 // If present - debug symbol
|
||||
|
||||
#define N_INDR 0xA // symbol refernced to another symbol
|
||||
|
||||
#define N_SETA 0x14 // Absolute set element symbol
|
||||
#define N_SETT 0x16 // Text set element symbol
|
||||
#define N_SETD 0x18 // Data set element symbol
|
||||
#define N_SETB 0x1A // Bss set element symbol
|
||||
|
||||
#define N_SETV 0x1C // Pointer to set vector in data area. (from LD)
|
||||
|
||||
#define N_WARNING 0x1E // Text has warnings
|
||||
|
||||
// Weak symbols
|
||||
#define N_WEAKU 0x0D // Weak undefined
|
||||
#define N_WEAKA 0x0E // Weak Absolute
|
||||
#define N_WEAKT 0x0F // Weak Text
|
||||
#define N_WEAKD 0x10 // Weak Data
|
||||
#define N_WEAKB 0x11 // Weak BSS
|
||||
|
||||
//=======================
|
||||
|
||||
struct relocation_info
|
||||
{
|
||||
int32 r_address; // Adress (within segment) to be relocated
|
||||
uint32 r_symbolnum:24;// The meaning of r_symbolnum depends on r_extern
|
||||
uint32 r_pcrel:1; // Nonzero means value is a pc-relative offset
|
||||
uint32 r_length:2; // Length (exp of 2) of the field to be relocated.
|
||||
uint32 r_extern:1; // 1 => relocate with value of symbol.
|
||||
// r_symbolnum is the index of the symbol
|
||||
// in file's the symbol table.
|
||||
// 0 => relocate with the address of a segment.
|
||||
// r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
|
||||
uint32 r_bsr:1;
|
||||
uint32 r_disp:1;
|
||||
uint32 r_pad:2;
|
||||
};
|
||||
|
||||
//============================
|
||||
// The SPARC_ prefix is added to the canonical names below to avoid a name
|
||||
// conflict if other architectures are added
|
||||
|
||||
enum reloc_type_sparc
|
||||
{
|
||||
SPARC_RELOC_8, SPARC_RELOC_16, SPARC_RELOC_32, // simplest relocs
|
||||
SPARC_RELOC_DISP8, SPARC_RELOC_DISP16, SPARC_RELOC_DISP32, // disp's (pc-rel)
|
||||
SPARC_RELOC_WDISP30, SPARC_RELOC_WDISP22, // SR word disp's
|
||||
SPARC_RELOC_HI22, SPARC_RELOC_22, // SR 22-bit relocs
|
||||
SPARC_RELOC_13, SPARC_RELOC_LO10, // SR 13&10-bit relocs
|
||||
SPARC_RELOC_SFA_BASE, SPARC_RELOC_SFA_OFF13, // SR S.F.A. relocs
|
||||
SPARC_RELOC_BASE10, SPARC_RELOC_BASE13, SPARC_RELOC_BASE22, // base_relative pic
|
||||
SPARC_RELOC_PC10, SPARC_RELOC_PC22, // special pc-rel pic
|
||||
SPARC_RELOC_JMP_TBL, // jmp_tbl_rel in pic
|
||||
SPARC_RELOC_SEGOFF16, // ShLib offset-in-seg
|
||||
SPARC_RELOC_GLOB_DAT, SPARC_RELOC_JMP_SLOT, SPARC_RELOC_RELATIVE, // rtld relocs
|
||||
};
|
||||
|
||||
struct reloc_info_sparc
|
||||
{
|
||||
uint32 r_address; // relocation address (offset in segment)
|
||||
uint32 r_index:24; // segment index or symbol index
|
||||
uint32 r_extern:1; // if F, r_index==SEG#, if T, SYM index
|
||||
uint32 :2; // unused
|
||||
uint32 r_type:5; // type of relocation to perform
|
||||
uint32 r_addend; // addend for relocation value
|
||||
};
|
||||
|
||||
CASSERT(sizeof(reloc_info_sparc) == 12);
|
||||
|
||||
#define N_PAGSIZ_SPARC(x) 0x02000
|
||||
#define N_SEGSIZ_SPARC(x) N_PAGSIZ_SPARC
|
||||
|
||||
#define N_TXTOFF_SPARC(x) ((N_MAGIC(x) == ZMAGIC) ? 0 : sizeof (struct exec))
|
||||
#define N_TXTADDR_SPARC(x) \
|
||||
((N_MAGIC(x) == OMAGIC) ? (x).a_entry \
|
||||
: ((N_MAGIC(x) == ZMAGIC) && ((x).a_entry < N_PAGSIZ_SPARC(x)) ? 0 \
|
||||
: N_PAGSIZ_SPARC(x)) \
|
||||
)
|
||||
|
||||
#define N_DATOFF_SPARC(x) (N_TXTOFF_SPARC(x) + (x).a_text)
|
||||
#define N_DATADDR_SPARC(x) \
|
||||
((N_MAGIC(x) == OMAGIC) ? (N_TXTADDR_SPARC(x) + (x).a_text) \
|
||||
: (N_SEGSIZ_SPARC(x)+((N_TXTADDR_SPARC(x)+(x).a_text-1) \
|
||||
& ~(N_SEGSIZ_SPARC(x)-1))))
|
||||
|
||||
#define N_BSSADDR_SPARC(x) (N_DATADDR_SPARC(x) + (x).a_data)
|
||||
|
||||
#define N_TRELOFF_SPARC(x) (N_DATOFF_SPARC(x) + (x).a_data)
|
||||
#define N_DRELOFF_SPARC(x) (N_TRELOFF_SPARC(x) + N_TRSIZE(x))
|
||||
#define N_SYMOFF_SPARC(x) (N_DRELOFF_SPARC(x) + N_DRSIZE(x))
|
||||
#define N_STROFF_SPARC(x) (N_SYMOFF_SPARC(x) + (x).a_syms)
|
||||
|
||||
|
||||
//============================
|
||||
// Dynamic loader info (restored from a binary form in pc_bsd.aout, not exact):
|
||||
|
||||
struct lddir_t
|
||||
{
|
||||
uint32 unknown0; // 8
|
||||
uint32 unknown1; // offset dword_5010
|
||||
uint32 ldinfo;
|
||||
};
|
||||
|
||||
struct ld_info_t
|
||||
{
|
||||
uint32 unknown0; // 0
|
||||
uint32 onemoretable;
|
||||
uint32 unknown1; // 0
|
||||
uint32 off_5060; // points to the end of this struct
|
||||
uint32 ldentry; // main dynamic loader entry
|
||||
uint32 imports;
|
||||
uint32 pairs; // pairs of symbol numbers
|
||||
uint32 symbols;
|
||||
uint32 unknown2; // 0
|
||||
uint32 unknown3; // 16h
|
||||
uint32 strings;
|
||||
uint32 unknown4; // 310h
|
||||
uint32 unknown5; // 4000h
|
||||
uint32 unknown6; // 148h
|
||||
uint32 unknown7; // offset dword_5000
|
||||
};
|
||||
|
||||
struct ld_symbol_t
|
||||
{
|
||||
uint32 nameoff; // offset from the beginning of the string table
|
||||
uint32 flags;
|
||||
#define AOUT_LD_FUNC 0x200
|
||||
#define AOUT_LD_DEF 0x004 // defined, otherwise - imported
|
||||
#define AOUT_LD_DATA 0x002 // data
|
||||
uint32 addr; // pointer to the object
|
||||
uint32 zero; // always zero?
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
76
idasdk76/ldr/aout/common.cpp
Normal file
76
idasdk76/ldr/aout/common.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_exec(exec &ex)
|
||||
{
|
||||
ex.a_info = swap32(ex.a_info);
|
||||
ex.a_text = swap32(ex.a_text);
|
||||
ex.a_data = swap32(ex.a_data);
|
||||
ex.a_bss = swap32(ex.a_bss);
|
||||
ex.a_syms = swap32(ex.a_syms);
|
||||
ex.a_entry = swap32(ex.a_entry);
|
||||
ex.a_trsize = swap32(ex.a_trsize);
|
||||
ex.a_drsize = swap32(ex.a_drsize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int get_aout_file_format_index(linput_t *li, exec *_ex)
|
||||
{
|
||||
exec &ex = *_ex;
|
||||
int i = 0;
|
||||
if ( qlread(li, &ex, sizeof(ex)) != sizeof(ex) )
|
||||
return false;
|
||||
|
||||
if ( N_BADMAG(ex) )
|
||||
{
|
||||
swap_exec(ex);
|
||||
switch ( N_MACHTYPE(ex) )
|
||||
{
|
||||
case M_386_NETBSD:
|
||||
case M_68K_NETBSD:
|
||||
case M_68K4K_NETBSD:
|
||||
case M_532_NETBSD:
|
||||
case M_SPARC:
|
||||
case M_SPARC_NETBSD:
|
||||
case M_PMAX_NETBSD:
|
||||
case M_VAX_NETBSD:
|
||||
case M_ALPHA_NETBSD:
|
||||
case M_ARM6_NETBSD:
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( N_MAGIC(ex) )
|
||||
{
|
||||
case NMAGIC:
|
||||
++i;
|
||||
case CMAGIC:
|
||||
++i;
|
||||
case ZMAGIC:
|
||||
++i;
|
||||
case OMAGIC:
|
||||
++i;
|
||||
case QMAGIC:
|
||||
if ( N_MACHTYPE(ex) == M_SPARC )
|
||||
break; // SPARC uses different TXTOFF
|
||||
|
||||
#ifdef DEBUG
|
||||
msg("magic=%04x text=%08x data=%08x symsize=%08x txtoff=%08x sum=%08x // qlsize=%08x\n", N_MAGIC(ex), ex.a_text, ex.a_data,
|
||||
N_SYMSIZE(ex), N_TXTOFF(ex), ex.a_text + ex.a_data + N_SYMSIZE(ex) + N_TXTOFF(ex),
|
||||
qlsize(li));
|
||||
#endif
|
||||
if ( qlsize(li) >= ex.a_text + ex.a_data + N_SYMSIZE(ex) + N_TXTOFF(ex) )
|
||||
break;
|
||||
if ( N_MAGIC(ex) == ZMAGIC
|
||||
&& qlsize(li) >= ex.a_text + ex.a_data + N_SYMSIZE(ex) )
|
||||
{
|
||||
i = 5; // OpenBSD demand-paged
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return i+1;
|
||||
}
|
||||
14
idasdk76/ldr/aout/makefile
Normal file
14
idasdk76/ldr/aout/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=aout
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)aout$(O) : $(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)ua.hpp \
|
||||
$(I)xref.hpp ../../module/sparc/notify_codes.hpp \
|
||||
../idaldr.h aout.cpp aout.h common.cpp
|
||||
Reference in New Issue
Block a user