update to ida 7.6, add builds
This commit is contained in:
439
idasdk76/ldr/intelomf/intelomf.cpp
Normal file
439
idasdk76/ldr/intelomf/intelomf.cpp
Normal file
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 4.20
|
||||
* Copyright (c) 2002 by Ilfak Guilfanov. (ig@datarescue.com)
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Intel OMF386
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "intelomf.hpp"
|
||||
#include "common.cpp"
|
||||
|
||||
static lmh h;
|
||||
static ea_t xea;
|
||||
static sel_t dsel = BADSEL;
|
||||
//--------------------------------------------------------------------------
|
||||
static void create32(
|
||||
sel_t sel,
|
||||
ea_t start_ea,
|
||||
ea_t end_ea,
|
||||
const char *name,
|
||||
const char *sclass)
|
||||
{
|
||||
set_selector(sel, 0);
|
||||
|
||||
segment_t s;
|
||||
s.sel = sel;
|
||||
s.start_ea = start_ea;
|
||||
s.end_ea = end_ea;
|
||||
s.align = saRelByte;
|
||||
s.comb = sclass != NULL && streq(sclass, "STACK") ? scStack : scPub;
|
||||
s.bitness = 1; // 32-bit
|
||||
|
||||
if ( !add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void show_segdefs(linput_t *li, uint32 offset, uint32 length)
|
||||
{
|
||||
if ( offset == 0 || length == 0 )
|
||||
return;
|
||||
qlseek(li, offset);
|
||||
int n = 0;
|
||||
for ( int i=0; i < length; )
|
||||
{
|
||||
if ( qltell(li) >= qlsize(li) )
|
||||
BAD_FILE:
|
||||
loader_failure("Corrupted segmentation info");
|
||||
segdef s;
|
||||
const int size = offsetof(segdef, combine_name);
|
||||
lread(li, &s, size);
|
||||
int nlen = read_pstring(li, s.combine_name, sizeof(s.combine_name));
|
||||
i += size + 1 + nlen;
|
||||
n++;
|
||||
|
||||
const char *sname = s.combine_name;
|
||||
const char *sclas = sname;
|
||||
if ( strnicmp(sname, "CODE", 4) == 0 )
|
||||
sclas = "CODE";
|
||||
if ( strnicmp(sname, "DATA", 4) == 0 )
|
||||
sclas = "DATA";
|
||||
if ( strnicmp(sname, "CONST", 5) == 0 )
|
||||
sclas = "CONST";
|
||||
if ( stricmp(sname, "STACK") == 0 )
|
||||
sclas = "STACK";
|
||||
if ( strchr(sname, ':') != NULL )
|
||||
continue;
|
||||
|
||||
int segsize = s.slimit + 1;
|
||||
if ( segsize < 0 || qltell(li) >= qlsize(li) )
|
||||
goto BAD_FILE;
|
||||
|
||||
if ( strcmp(sname, "DATA") == 0 )
|
||||
dsel = n;
|
||||
set_selector(n, 0);
|
||||
ea_t ea = free_chunk(inf_get_max_ea(), segsize, -(1<<s.align));
|
||||
create32(n, ea, ea+segsize, sname, sclas);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static ea_t getsea(ushort i)
|
||||
{
|
||||
segment_t *s = get_segm_by_sel(i & 0xFF);
|
||||
return s ? s->start_ea : BADADDR;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void show_pubdefs(linput_t *li, uint32 offset, uint32 length)
|
||||
{
|
||||
if ( offset == 0 || length == 0 )
|
||||
return;
|
||||
qlseek(li, offset);
|
||||
for ( int i=0; i < length; )
|
||||
{
|
||||
pubdef p;
|
||||
const int size = offsetof(pubdef, sym_name);
|
||||
if ( qlread(li, &p, size) != size )
|
||||
loader_failure("Corrupted pubdefs");
|
||||
int nlen = read_pstring(li, p.sym_name, sizeof(p.sym_name));
|
||||
i += size + 1 + nlen;
|
||||
|
||||
ea_t sea = getsea(p.PUB_segment);
|
||||
if ( sea != BADADDR )
|
||||
{
|
||||
sea += p.PUB_offset;
|
||||
add_entry(sea, sea, p.sym_name, segtype(sea) == SEG_CODE, AEF_IDBENC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void show_extdefs(linput_t *li, uint32 offset, uint32 length)
|
||||
{
|
||||
if ( offset == 0 || length == 0 )
|
||||
return;
|
||||
qlseek(li, offset);
|
||||
|
||||
uchar ss = inf_is_64bit() ? 8 : 4;
|
||||
inf_set_specsegs(ss);
|
||||
int16 segsize = ss * h.num_externals;
|
||||
if ( !is_mul_ok(uint16(ss), uint16(h.num_externals))
|
||||
|| segsize < 0
|
||||
|| segsize < h.num_externals )
|
||||
{
|
||||
BAD_EXTDEFS:
|
||||
loader_failure("Corrupted extdefs");
|
||||
}
|
||||
sel_t sel = h.num_segs+1;
|
||||
set_selector(sel, 0);
|
||||
xea = free_chunk(inf_get_max_ea(), segsize, -15);
|
||||
create32(sel, xea, xea+segsize, "XTRN", "XTRN");
|
||||
|
||||
int n = 0;
|
||||
for ( int i=0; i < length; )
|
||||
{
|
||||
extdef p;
|
||||
const int size = offsetof(extdef, allocate_len);
|
||||
if ( qlread(li, &p, size) != size )
|
||||
goto BAD_EXTDEFS;
|
||||
p.allocate_len.len_4 = 0;
|
||||
if ( p.allocate != 0 )
|
||||
{
|
||||
ask_for_feedback("extdef.allocate\n");
|
||||
lread(li, &p.allocate_len.len_4, sizeof(p.allocate_len.len_4));
|
||||
}
|
||||
int nlen = read_pstring(li, p.sym_name, sizeof(p.sym_name));
|
||||
i += size + 1 + nlen;
|
||||
|
||||
ea_t a = xea + 4 * n++;
|
||||
set_name(a, p.sym_name, SN_IDBENC);
|
||||
if ( p.allocate )
|
||||
put_dword(a, p.allocate_len.len_4);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void read_text(linput_t *li)
|
||||
{
|
||||
text txt;
|
||||
const int size = offsetof(text, segment);
|
||||
if ( qlread(li, &txt, size) != size || txt.length < 0 )
|
||||
loader_failure("Corrupted text data");
|
||||
if ( txt.length != 0 )
|
||||
{
|
||||
qoff64_t fptr = qltell(li);
|
||||
ea_t sea = getsea(txt.txt_IN);
|
||||
if ( sea != BADADDR )
|
||||
{
|
||||
ea_t start = sea + txt.txt_offset;
|
||||
ea_t end = start + txt.length;
|
||||
uint64 fsize = qlsize(li);
|
||||
segment_t *s = getseg(start);
|
||||
if ( start < sea
|
||||
|| end < start
|
||||
|| fptr > fsize
|
||||
|| fsize-fptr < txt.length
|
||||
|| s == NULL
|
||||
|| s->end_ea < end )
|
||||
{
|
||||
loader_failure("Corrupted text data");
|
||||
}
|
||||
if ( change_storage_type(start, end, STT_VA) != eOk )
|
||||
INTERR(20060);
|
||||
file2base(li, fptr, start, end, FILEREG_PATCHABLE);
|
||||
}
|
||||
qlseek(li, fptr+txt.length);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void read_fixup(linput_t *li)
|
||||
{
|
||||
fixup fix;
|
||||
const int size = offsetof(fixup, fixups);
|
||||
if ( qlread(li, &fix, size) != size || fix.length < 0 )
|
||||
loader_failure("Corrupted fixups");
|
||||
qoff64_t fptr = qltell(li);
|
||||
ea_t sea = getsea(fix.where_IN);
|
||||
if ( sea != BADADDR )
|
||||
{
|
||||
validate_array_count(li, &fix.length, 1, "Fixup count");
|
||||
uchar *b = (uchar *)qalloc(fix.length);
|
||||
if ( b == NULL )
|
||||
nomem("read_fixup");
|
||||
lread(li, b, fix.length);
|
||||
|
||||
// show_hex(b, fix.length, "\nFIXUP SEG %04X, %04X BYTES, KIND %02X\n",
|
||||
// fix.where_IN,
|
||||
// fix.length,
|
||||
// b[0]);
|
||||
|
||||
const uchar *ptr = b;
|
||||
const uchar *end = b + fix.length;
|
||||
while ( ptr < end )
|
||||
{
|
||||
uint32 where_offset = 0;
|
||||
uint32 what_offset = 0;
|
||||
ushort what_in = 9;
|
||||
bool selfrel = false;
|
||||
bool isfar = false;
|
||||
fixup_data_t fd(FIXUP_OFF32);
|
||||
switch ( *ptr++ )
|
||||
{
|
||||
case 0x2C: // GEN
|
||||
isfar = true;
|
||||
ask_for_feedback("Untested relocation type");
|
||||
case 0x24: // GEN
|
||||
where_offset = readdw(ptr, false);
|
||||
what_offset = readdw(ptr, false);
|
||||
what_in = (ushort)readdw(ptr, false);
|
||||
break;
|
||||
case 0x2D:
|
||||
isfar = true;
|
||||
case 0x25: // INTRA
|
||||
where_offset = readdw(ptr, false);
|
||||
what_offset = readdw(ptr, false);
|
||||
what_in = fix.where_IN;
|
||||
break;
|
||||
case 0x2A: // CALL
|
||||
where_offset = readdw(ptr, false);
|
||||
what_offset = 0;
|
||||
what_in = (ushort)readdw(ptr, false);
|
||||
selfrel = true;
|
||||
break;
|
||||
case 0x2E: // OFF32?
|
||||
isfar = true;
|
||||
case 0x26:
|
||||
where_offset = readdw(ptr, false);
|
||||
what_offset = 0;
|
||||
what_in = (ushort)readdw(ptr, false);
|
||||
break;
|
||||
default:
|
||||
ask_for_feedback("Unknown relocation type %02X", ptr[-1]);
|
||||
add_pgm_cmt("!!! Unknown relocation type %02X", ptr[-1]);
|
||||
break;
|
||||
}
|
||||
ea_t source = sea + where_offset;
|
||||
ea_t target = BADADDR;
|
||||
switch ( what_in >> 12 )
|
||||
{
|
||||
case 0x02: // segments
|
||||
target = getsea(what_in);
|
||||
break;
|
||||
case 0x06: // externs
|
||||
target = xea + 4 * ((what_in & 0xFFF) - 1);
|
||||
fd.set_extdef();
|
||||
break;
|
||||
default:
|
||||
ask_for_feedback("Unknown relocation target %04X", what_in);
|
||||
add_pgm_cmt("!!! Unknown relocation target %04X", what_in);
|
||||
break;
|
||||
}
|
||||
fd.set_target_sel();
|
||||
if ( !fd.is_extdef() )
|
||||
{
|
||||
target += what_offset;
|
||||
what_offset = 0;
|
||||
}
|
||||
fd.off = target - fd.get_base();
|
||||
fd.displacement = what_offset;
|
||||
target += what_offset;
|
||||
if ( selfrel )
|
||||
target -= source + 4;
|
||||
fd.set(source);
|
||||
put_dword(source, target);
|
||||
if ( isfar )
|
||||
{
|
||||
fd.set_type_and_flags(FIXUP_SEG16);
|
||||
fd.set(source+4);
|
||||
put_word(source+4, fd.sel);
|
||||
}
|
||||
}
|
||||
qfree(b);
|
||||
}
|
||||
qlseek(li, fptr + fix.length);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void read_iterat(linput_t *li)
|
||||
{
|
||||
iterat itr;
|
||||
const int size = offsetof(iterat, text) + offsetof(temp, value);
|
||||
lread(li, &itr, size);
|
||||
itr.text.value = NULL;
|
||||
if ( itr.text.length != 0 )
|
||||
{
|
||||
if ( itr.text.length < 0 || itr.it_count < 0 )
|
||||
BAD_FILE:
|
||||
loader_failure("Corrupted iterated data");
|
||||
qoff64_t fptr = qltell(li);
|
||||
ea_t sea = getsea(itr.it_segment);
|
||||
if ( sea != BADADDR )
|
||||
{
|
||||
uint64 fsize = qlsize(li);
|
||||
ea_t start = sea + itr.it_offset;
|
||||
segment_t *s = getseg(start);
|
||||
if ( start < sea
|
||||
|| fptr > fsize
|
||||
|| fsize-fptr < itr.text.length
|
||||
|| !is_mul_ok(uint32(itr.text.length), uint32(itr.it_count))
|
||||
|| s == NULL )
|
||||
{
|
||||
goto BAD_FILE;
|
||||
}
|
||||
uint32 total = itr.text.length * itr.it_count;
|
||||
ea_t final_end = start + total;
|
||||
if ( final_end < start || final_end > s->end_ea )
|
||||
goto BAD_FILE;
|
||||
if ( change_storage_type(start, final_end, STT_VA) != eOk )
|
||||
INTERR(20061);
|
||||
for ( int i=0; i < itr.it_count; i++ )
|
||||
{
|
||||
ea_t end = start + itr.text.length;
|
||||
file2base(li, fptr, start, end, FILEREG_PATCHABLE);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
qlseek(li, fptr+itr.text.length);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void show_txtfixs(linput_t *li, uint32 offset, uint32 length)
|
||||
{
|
||||
if ( offset == 0 || length == 0 )
|
||||
return;
|
||||
uint64 fsize = qlsize(li);
|
||||
uint64 eoff = offset + length;
|
||||
if ( eoff < offset || offset > fsize || eoff > fsize )
|
||||
loader_failure("Corrupted fixups");
|
||||
qlseek(li, offset);
|
||||
while ( qltell(li) < eoff )
|
||||
{
|
||||
char type;
|
||||
lread(li, &type, sizeof(type));
|
||||
switch ( type )
|
||||
{
|
||||
case 0:
|
||||
read_text(li);
|
||||
break;
|
||||
case 1:
|
||||
read_fixup(li);
|
||||
break;
|
||||
case 2:
|
||||
read_iterat(li);
|
||||
break;
|
||||
default:
|
||||
ask_for_feedback("txtfix.blk_type == %d!\n", type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
if ( is_intelomf_file(li) )
|
||||
{
|
||||
*fileformatname = "Intel OMF386";
|
||||
*processor = "metapc";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
set_processor_type("metapc", SETPROC_LOADER);
|
||||
|
||||
qlseek(li, 1);
|
||||
lread(li, &h, sizeof(h));
|
||||
|
||||
toc_p1 toc;
|
||||
lread(li, &toc, sizeof(toc));
|
||||
|
||||
// we add one to skip the magic byte
|
||||
show_segdefs(li, toc.SEGDEF_loc+1, toc.SEGDEF_len);
|
||||
show_pubdefs(li, toc.PUBDEF_loc+1, toc.PUBDEF_len);
|
||||
show_extdefs(li, toc.EXTDEF_loc+1, toc.EXTDEF_len);
|
||||
show_txtfixs(li, toc.TXTFIX_loc+1, toc.TXTFIX_len);
|
||||
|
||||
if ( dsel != BADSEL )
|
||||
set_default_dataseg(dsel);
|
||||
add_pgm_cmt("Module: %*.*s", h.mod_name[0], uchar(h.mod_name[0]), &h.mod_name[1]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
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,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
Reference in New Issue
Block a user