update to ida 7.6, add builds
This commit is contained in:
427
idasdk76/ldr/aif/aif.cpp
Normal file
427
idasdk76/ldr/aif/aif.cpp
Normal file
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-97 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
* ARM Image File (AIF) Loader
|
||||
* ---------------------------
|
||||
* This module allows IDA to load ARM image files into
|
||||
* its database and to disassemble them correctly.
|
||||
*
|
||||
* NOTE: Compressed image files are not supported
|
||||
* Self-relocating image files are not supported
|
||||
* Thumb image files are not supported
|
||||
* Only 32-bit image files are supported
|
||||
*
|
||||
* This module automatically detects the byte sex and sets inf.mf
|
||||
* variable accrodingly.
|
||||
*
|
||||
* The debug information is partially processed.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "../idaldr.h"
|
||||
#include "aif.h"
|
||||
#include "../aof/aof.h"
|
||||
|
||||
// the following function is defined to be used by aifcmn.cpp
|
||||
// included below (see also efd/aif.cpp)
|
||||
inline bool is_mf() { return inf_is_be(); }
|
||||
|
||||
#include "aifcmn.cpp"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *)
|
||||
{
|
||||
if ( !is_aif_file(li) )
|
||||
return 0;
|
||||
|
||||
*fileformatname = "ARM Image File";
|
||||
*processor = "arm";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create a section.
|
||||
static void create_section(
|
||||
ushort sel,
|
||||
ea_t start_ea,
|
||||
ea_t end_ea,
|
||||
const char *name,
|
||||
const char *classname)
|
||||
{
|
||||
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 = scPub;
|
||||
s.bitness = 1; // 32-bit
|
||||
int flags = ADDSEG_SPARSE | ADDSEG_NOSREG | ADDSEG_NOTRUNC;
|
||||
if ( !add_segm_ex(&s, name, classname, flags) )
|
||||
loader_failure();
|
||||
|
||||
segment_t *sptr = getseg(start_ea);
|
||||
set_arm_segm_flags(start_ea, 2 << 10); // alignment
|
||||
sptr->update();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// The assembler and the compiler generate lots of meaningless symbols.
|
||||
// We will ignore them.
|
||||
static bool special_name(const char *name)
|
||||
{
|
||||
int i;
|
||||
if ( name[0] == '\0' )
|
||||
return true;
|
||||
if ( name[0] == '$' )
|
||||
return true;
|
||||
const char *ptr = strchr(name,'$');
|
||||
if ( ptr != NULL && ptr[1] == '$' )
|
||||
return true;
|
||||
|
||||
static const char *const ex[] =
|
||||
{
|
||||
"_etext",
|
||||
"_edata",
|
||||
"_end",
|
||||
"!!!"
|
||||
};
|
||||
for ( i=0; i < qnumber(ex); i++ )
|
||||
if ( strcmp(ex[i],name) == 0 )
|
||||
return true;
|
||||
|
||||
static const char *const data_names[] = { "x$constdata", "x$litpool" };
|
||||
for ( i=0; i < qnumber(data_names); i++ )
|
||||
if ( strncmp(name, data_names[i], strlen(data_names[i])) == 0 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// The debug information says that "xlitpool" symbols have "CODE" type.
|
||||
// We cannot base on this because doing so we would convert
|
||||
// xlitpools to instructions.
|
||||
// So, we will look at the names and if a location has
|
||||
// "xlitpool" or similar name, we will not convert it to instructions
|
||||
// even it is marked as "CODE".
|
||||
//
|
||||
// Later: I decided not to use all those names at all.
|
||||
|
||||
static bool is_true_text_symbol(dsym_t *ds,const char *name)
|
||||
{
|
||||
if ( ds->is_text() )
|
||||
{
|
||||
static const char *const data_names[] = { "x$constdata", "x$litpool" };
|
||||
for ( int i=0; i < qnumber(data_names); i++ )
|
||||
if ( strncmp(name,data_names[i],strlen(data_names[i])) == 0 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Process debugging information item and try to incorporate it into
|
||||
// the database.
|
||||
// NOTE: This function does not process all debugging information.
|
||||
// It knows only about some types of debugingo.
|
||||
static size_t process_item(uchar *di, size_t disize, section_t *sect)
|
||||
{
|
||||
uchar *const end = di + disize;
|
||||
if ( disize < 4 )
|
||||
return 0;
|
||||
uint32 fw = *(uint32 *)di;
|
||||
if ( inf_is_be() )
|
||||
fw = swap32(fw);
|
||||
size_t len = fw >> 16;
|
||||
if ( len == 0 || len > disize )
|
||||
return 0;
|
||||
switch ( fw & 0xFFFF )
|
||||
{
|
||||
case AIF_DEB_SECT: // section
|
||||
if ( disize < sizeof(section_t) )
|
||||
return 0;
|
||||
sect = (section_t *)di;
|
||||
if ( inf_is_be() )
|
||||
swap_section(sect);
|
||||
if ( sect->debugsize != 0 )
|
||||
{
|
||||
len = sect->debugsize;
|
||||
if ( len > disize )
|
||||
return 0;
|
||||
}
|
||||
switch ( sect->lang )
|
||||
{
|
||||
case LANG_C:
|
||||
add_extra_cmt(sect->codestart, true, "C source level debugging data is present");
|
||||
break;
|
||||
case LANG_PASCAL:
|
||||
add_extra_cmt(sect->codestart, true, "Pascal source level debugging data is present");
|
||||
break;
|
||||
case LANG_FORTRAN:
|
||||
add_extra_cmt(sect->codestart, true, "Fortran-77 source level debugging data is present");
|
||||
break;
|
||||
case LANG_ASM:
|
||||
add_extra_cmt(sect->codestart, true, "ARM assembler line number data is present");
|
||||
break;
|
||||
}
|
||||
if ( sect->lang == LANG_NONE )
|
||||
{
|
||||
size_t nsyms = size_t(sect->name);
|
||||
dsym_t *ds = (dsym_t *)(sect+1);
|
||||
char *str = (char *)(ds+nsyms);
|
||||
if ( !is_mul_ok(nsyms, sizeof(dsym_t)) || ds+nsyms < ds || str >= (char *)end )
|
||||
return 0;
|
||||
bool use_pascal = swap_symbols(ds, str, end, nsyms);
|
||||
for ( int i=0; i < nsyms; i++,ds++ )
|
||||
{
|
||||
if ( ds->sym & ASD_16BITSYM )
|
||||
continue;
|
||||
size_t off = size_t(ds->sym & ASD_SYMOFF);
|
||||
char *name = str + off + use_pascal;
|
||||
if ( name < str || name >= (char *)end )
|
||||
continue;
|
||||
if ( special_name(name) )
|
||||
continue;
|
||||
if ( ds->sym == ASD_ABSSYM ) // if the symbol is absolute
|
||||
{
|
||||
add_pgm_cmt("%s = 0x%X", name, ds->value);
|
||||
}
|
||||
else if ( is_mapped(ds->value) )
|
||||
{
|
||||
if ( ds->sym & ASD_GLOBSYM )
|
||||
{
|
||||
add_entry(ds->value, ds->value, name, is_true_text_symbol(ds, name), AEF_IDBENC);
|
||||
}
|
||||
else
|
||||
{
|
||||
force_name(ds->value, name, SN_IDBENC);
|
||||
if ( is_true_text_symbol(ds, name) )
|
||||
auto_make_code(ds->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char name[64];
|
||||
const uchar *nptr = (const uchar *)§->name;
|
||||
size_t namelen = *nptr++;
|
||||
if ( namelen > end-nptr || namelen >= sizeof(name) )
|
||||
return 0;
|
||||
qstrncpy(name, (const char *)nptr, sizeof(name));
|
||||
name[namelen] = '\0';
|
||||
if ( sect->codestart != 0 )
|
||||
add_extra_cmt(sect->codestart, true, "Section \"%s\", size 0x%X",name,sect->codesize);
|
||||
if ( sect->datastart != 0 )
|
||||
add_extra_cmt(sect->datastart, true, "Section \"%s\", size 0x%X",name,sect->datasize);
|
||||
}
|
||||
#if 0
|
||||
if ( sect->fileinfo != 0 ) // fileinfo is present?
|
||||
process_item(di+size_t(sect->fileinfo),sect);
|
||||
#endif
|
||||
break;
|
||||
case AIF_DEB_FDEF: // procedure/function definition
|
||||
deb(IDA_DEBUG_LDR, "procedure/function definition\n");
|
||||
break;
|
||||
case AIF_DEB_ENDP: // endproc
|
||||
deb(IDA_DEBUG_LDR, "endproc\n");
|
||||
break;
|
||||
case AIF_DEB_VAR: // variable
|
||||
deb(IDA_DEBUG_LDR, "variable\n");
|
||||
break;
|
||||
case AIF_DEB_TYPE: // type
|
||||
deb(IDA_DEBUG_LDR, "type\n");
|
||||
break;
|
||||
case AIF_DEB_STRU: // struct
|
||||
deb(IDA_DEBUG_LDR, "struct\n");
|
||||
break;
|
||||
case AIF_DEB_ARRAY: // array
|
||||
deb(IDA_DEBUG_LDR, "array\n");
|
||||
break;
|
||||
case AIF_DEB_RANGE: // subrange
|
||||
deb(IDA_DEBUG_LDR, "subrange\n");
|
||||
break;
|
||||
case AIF_DEB_SET: // set
|
||||
deb(IDA_DEBUG_LDR, "set\n");
|
||||
break;
|
||||
case AIF_DEB_FILE: // fileinfo
|
||||
deb(IDA_DEBUG_LDR, "fileinfo\n");
|
||||
break;
|
||||
case AIF_DEB_CENUM: // contiguous enumeration
|
||||
deb(IDA_DEBUG_LDR, "contiguous enumeration\n");
|
||||
break;
|
||||
case AIF_DEB_DENUM: // discontiguous enumeration
|
||||
deb(IDA_DEBUG_LDR, "discontiguous enumeration\n");
|
||||
break;
|
||||
case AIF_DEB_FDCL: // procedure/function declaration
|
||||
deb(IDA_DEBUG_LDR, "procedure/function declaration\n");
|
||||
break;
|
||||
case AIF_DEB_SCOPE: // begin naming scope
|
||||
deb(IDA_DEBUG_LDR, "begin naming scope\n");
|
||||
break;
|
||||
case AIF_DEB_ENDS: // end naming scope
|
||||
deb(IDA_DEBUG_LDR, "end naming scope\n");
|
||||
break;
|
||||
case AIF_DEB_BITF: // bitfield
|
||||
deb(IDA_DEBUG_LDR, "bitfield\n");
|
||||
break;
|
||||
case AIF_DEB_MACRO: // macro definition
|
||||
deb(IDA_DEBUG_LDR, "macro definition\n");
|
||||
break;
|
||||
case AIF_DEB_ENDM: // macro undefinition
|
||||
deb(IDA_DEBUG_LDR, "macro undefinition\n");
|
||||
break;
|
||||
case AIF_DEB_CLASS: // class
|
||||
deb(IDA_DEBUG_LDR, "class\n");
|
||||
break;
|
||||
case AIF_DEB_UNION: // union
|
||||
deb(IDA_DEBUG_LDR, "union\n");
|
||||
break;
|
||||
case AIF_DEB_FPMAP: // FP map fragment
|
||||
deb(IDA_DEBUG_LDR, "FP map fragment\n");
|
||||
break;
|
||||
default:
|
||||
msg("unknown (0x%u.)!!!\n", fw & 0xFFFF);
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
aif_header_t hd;
|
||||
set_processor_type("arm", SETPROC_LOADER);
|
||||
lread(li, &hd, sizeof(hd));
|
||||
inf_set_be(match_zero_code(&hd) != 1);
|
||||
if ( (hd.address_mode & 0xFF) != 32 )
|
||||
{
|
||||
if ( (hd.address_mode & 0xFF) != 0 )
|
||||
loader_failure("26-bit modules are not supported");
|
||||
msg("Old AIF format file...");
|
||||
}
|
||||
if ( hd.decompress_code != NOP )
|
||||
loader_failure("Compressed modules are not supported");
|
||||
if ( hd.self_reloc_code != NOP )
|
||||
loader_failure("Self-relocating modules are not supported");
|
||||
|
||||
inf_set_baseaddr(0);
|
||||
int isexec = is_bl(hd.entry_point);
|
||||
qoff64_t offset = sizeof(aif_header_t);
|
||||
ea_t start = hd.image_base;
|
||||
if ( isexec )
|
||||
{
|
||||
start += sizeof(aif_header_t);
|
||||
hd.readonly_size -= sizeof(aif_header_t);
|
||||
}
|
||||
uint64 rest = qlsize(li) - offset;
|
||||
if ( rest < hd.readonly_size )
|
||||
BAD_FILE:
|
||||
loader_failure("Corrupted file");
|
||||
ea_t end = start + hd.readonly_size;
|
||||
file2base(li, offset, start, end, FILEREG_PATCHABLE);
|
||||
create_section(1, start, end, NAME_CODE, CLASS_CODE);
|
||||
offset += hd.readonly_size;
|
||||
if ( hd.readwrite_size != 0 )
|
||||
{
|
||||
rest = qlsize(li) - offset;
|
||||
if ( rest < hd.readwrite_size )
|
||||
goto BAD_FILE;
|
||||
start = (hd.address_mode & AIF_SEP_DATA) ? hd.data_base : end;
|
||||
end = start + hd.readwrite_size;
|
||||
file2base(li, offset, start, end, FILEREG_PATCHABLE);
|
||||
create_section(2, start, end, NAME_DATA, CLASS_DATA);
|
||||
offset += hd.readwrite_size;
|
||||
}
|
||||
if ( hd.zero_init_size != 0 )
|
||||
{
|
||||
start = end;
|
||||
end = start + hd.zero_init_size;
|
||||
create_section(3, start, end, NAME_BSS, CLASS_BSS);
|
||||
}
|
||||
create_filename_cmt();
|
||||
|
||||
if ( isexec )
|
||||
hd.entry_point = hd.image_base
|
||||
+ offsetof(aif_header_t,entry_point)
|
||||
+ ((hd.entry_point & ~BLMASK) << 2)
|
||||
+ 8;
|
||||
inf_set_start_cs(1);
|
||||
inf_set_start_ip(hd.entry_point);
|
||||
inf_set_start_ea(hd.entry_point);
|
||||
|
||||
validate_array_count(li, &hd.debug_size, 1, "Size of debug info", offset);
|
||||
if ( hd.debug_size != 0 )
|
||||
{
|
||||
msg("Debugging information is present (%u bytes at file offset 0x%" FMT_64 "X)...\n",
|
||||
hd.debug_size, offset);
|
||||
uchar *di = qalloc_array<uchar>(size_t(hd.debug_size));
|
||||
if ( di == NULL )
|
||||
nomem("AIF debugging info");
|
||||
qlseek(li, offset);
|
||||
lread(li, di, size_t(hd.debug_size));
|
||||
uchar *ptr = di;
|
||||
uchar *diend = di + size_t(hd.debug_size);
|
||||
section_t *sect = NULL;
|
||||
while ( ptr < diend )
|
||||
{
|
||||
size_t len = process_item(ptr, diend-ptr, sect);
|
||||
if ( len == 0 )
|
||||
{
|
||||
warning("Corrupted debug info");
|
||||
break;
|
||||
}
|
||||
ptr += len;
|
||||
}
|
||||
qfree(di);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
177
idasdk76/ldr/aif/aif.h
Normal file
177
idasdk76/ldr/aif/aif.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-97 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
* ARM Image File Format
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AIF_H__
|
||||
#define __AIF_H__
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct aif_header_t
|
||||
{
|
||||
uint32 decompress_code;// BL or NOP if the image is not compressed.
|
||||
uint32 self_reloc_code;// BL or NOP if the image is not self-relocating.
|
||||
uint32 zero_init; // (or DBGInit) BL or NOP if the image has none.
|
||||
uint32 entry_point; // BL or EntryPoint offset
|
||||
uint32 program_exit; // usually SWI instruction
|
||||
uint32 readonly_size; // Includes header size if executable AIF;
|
||||
// excludes header size if non-executable AIF
|
||||
uint32 readwrite_size; // Exact size (a multiple of 4 bytes).
|
||||
uint32 debug_size; // Exact size (a multiple of 4 bytes).
|
||||
uint32 zero_init_size; // Exact size (a multiple of 4 bytes).
|
||||
uint32 debug_type; // bitwise OR of the following:
|
||||
#define AIF_DEBUG_NONE 0
|
||||
#define AIF_DEBUG_LOW 1 // Low-level debugging data is present
|
||||
#define AIF_DEBUG_SRC 2 // Source level (ASD) debugging data is present
|
||||
uint32 image_base; // Address where the image (code) was linked.
|
||||
uint32 work_space; // Minimum work space (in bytes) to be reserved by a
|
||||
// self-moving relocatable image.
|
||||
uint32 address_mode; // 26/32 + 3 flag bytes LS byte contains 26 or 32;
|
||||
// bit 8 set when using a separate data base.
|
||||
#define AIF_SEP_DATA 0x100 // if set, data_base is meaningful.
|
||||
uint32 data_base; // Address where the image data was linked.
|
||||
uint32 reserved[2]; // Two reserved words (initially 0)
|
||||
uint32 debug_init; // NOP if unused.
|
||||
uint32 zero_code[15]; // Zero-init code.
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
#define ZERO_CODE1 \
|
||||
0xE04EC00F, 0xE08FC00C, 0xE99C000F, \
|
||||
0xE24CC010, 0xE59C2030, 0xE3120C01, 0x159CC034, \
|
||||
0x008CC000, 0xE08CC001, 0xE3A00000, 0xE3530000, \
|
||||
0xD1A0F00E, 0xE48C0004, 0xE2533004, 0xEAFFFFFB
|
||||
|
||||
#define ZERO_CODE2 \
|
||||
0xE04EC00F, 0xE08FC00C, 0xE99C0017, \
|
||||
0xE24CC010, 0xE08CC000, 0xE08CC001, 0xE3A00000, \
|
||||
0xE3A01000, 0xE3A02000, 0xE3A03000, 0xE3540000, \
|
||||
0xD1A0F00E, 0xE8AC000F, 0xE2544010, 0xEAFFFFFB,
|
||||
|
||||
#define NOP 0xE1A00000L // opcode of NOP instruction
|
||||
#define BL 0xEB000000L // opcode of BL instruction
|
||||
#define BLMASK 0xFF000000L // mask to check BL instruction
|
||||
|
||||
// is BL instruction opcode?
|
||||
inline int is_bl(uint32 code) { return (code & BLMASK) == BL; }
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Debug item codes:
|
||||
#define AIF_DEB_SECT 1 // section
|
||||
#define AIF_DEB_FDEF 2 // procedure/function definition
|
||||
#define AIF_DEB_ENDP 3 // endproc
|
||||
#define AIF_DEB_VAR 4 // variable
|
||||
#define AIF_DEB_TYPE 5 // type
|
||||
#define AIF_DEB_STRU 6 // struct
|
||||
#define AIF_DEB_ARRAY 7 // array
|
||||
#define AIF_DEB_RANGE 8 // subrange
|
||||
#define AIF_DEB_SET 9 // set
|
||||
#define AIF_DEB_FILE 10 // fileinfo
|
||||
#define AIF_DEB_CENUM 11 // contiguous enumeration
|
||||
#define AIF_DEB_DENUM 12 // discontiguous enumeration
|
||||
#define AIF_DEB_FDCL 13 // procedure/function declaration
|
||||
#define AIF_DEB_SCOPE 14 // begin naming scope
|
||||
#define AIF_DEB_ENDS 15 // end naming scope
|
||||
#define AIF_DEB_BITF 16 // bitfield
|
||||
#define AIF_DEB_MACRO 17 // macro definition
|
||||
#define AIF_DEB_ENDM 18 // macro undefinition
|
||||
#define AIF_DEB_CLASS 19 // class
|
||||
#define AIF_DEB_UNION 20 // union
|
||||
#define AIF_DEB_FPMAP 32 // FP map fragment
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct section_t
|
||||
{
|
||||
uint32 code; // Section code and length
|
||||
uchar lang; // Language codes:
|
||||
#define LANG_NONE 0 // Low-level debugging data only
|
||||
#define LANG_C 1 // C source level debugging data
|
||||
#define LANG_PASCAL 2 // Pascal source level debugging data
|
||||
#define LANG_FORTRAN 3 // Fortran-77 source level debugging data
|
||||
#define LANG_ASM 4 // ARM assembler line number data
|
||||
uchar flags; // Format is unknown :(
|
||||
uchar reserved;
|
||||
uchar asdversion; // ASD version.
|
||||
#define ASD_VERSION 2
|
||||
uint32 codestart; // Address of first instruction in this section,
|
||||
// relocated by the linker.
|
||||
uint32 datastart; // Address of start of static data for this section,
|
||||
// relocated by the linker.
|
||||
uint32 codesize; // Byte size of executable code in this section.
|
||||
uint32 datasize; // Byte size of the static data in this section.
|
||||
uint32 fileinfo; // Offset in the debugging area of the fileinfo item
|
||||
// for this section (0 if no fileinfo item present).
|
||||
// The fileinfo field is 0 if no source file
|
||||
// information is present.
|
||||
uint32 debugsize; // Total byte length of debug data for this section.
|
||||
uint32 name; // ...or nsyms. String or integer. The name field
|
||||
// contains the program name for Pascal and Fortran
|
||||
// programs. For C programs it contains a name derived
|
||||
// by the compiler from the root filename (notionally
|
||||
// a module name). In each case, the name is similar
|
||||
// to a variable name in the source language. For a
|
||||
// low-level debugging section (language = 0), the
|
||||
// field is treated as a four-byte integer giving the
|
||||
// number of symbols following.
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Debug symbol types:
|
||||
struct dsym_t
|
||||
{
|
||||
uint32 sym; // Flags + byte offset in string table of symbol name.
|
||||
#define ASD_SYMOFF 0x00FFFFFFL
|
||||
// sym encodes an index into the string table in the 24 least
|
||||
// significant bits, and the following flag values in the
|
||||
// eight most significant bits:
|
||||
#define ASD_ABSSYM 0x00000000L // if the symbol is absolute
|
||||
#define ASD_GLOBSYM 0x01000000L // if the symbol is global
|
||||
#define ASD_SYMMASK 0x06000000L // mask to determine the symbol type
|
||||
#define ASD_TEXTSYM 0x02000000L // if the symbol names code
|
||||
#define ASD_DATASYM 0x04000000L // if the symbol names data
|
||||
#define ASD_ZINITSYM 0x06000000L // if the symbol names 0-initialized data
|
||||
#define ASD_16BITSYM 0x10000000L // bit set if the symbol is a Thumb symbol
|
||||
uint32 value; // the symbol's value.
|
||||
int is_text(void) { return (sym & ASD_SYMMASK) == ASD_TEXTSYM; }
|
||||
int is_data(void) { return (sym & ASD_SYMMASK) == ASD_DATASYM; }
|
||||
int is_bss(void) { return (sym & ASD_SYMMASK) == ASD_ZINITSYM; }
|
||||
};
|
||||
|
||||
/*
|
||||
Several of the debugging data items (eg. procedure and variable) have a type
|
||||
word field to identify their data type. This field contains
|
||||
in the most significant 24 bits, a code to identify a base
|
||||
in the least significant 8 bits, a pointer count:
|
||||
0 denotes the type itself
|
||||
1 denotes a pointer to the type
|
||||
2 denotes a pointer to a pointer
|
||||
|
||||
void 0
|
||||
signed integers
|
||||
single byte 10
|
||||
halfword 11
|
||||
word 12
|
||||
double word 13
|
||||
unsigned integers
|
||||
single byte 20
|
||||
halfword 21
|
||||
word 22
|
||||
double word 23
|
||||
floating point
|
||||
float 30
|
||||
double 31
|
||||
int32 double 32
|
||||
complex
|
||||
single complex 41
|
||||
double complex 42
|
||||
functions
|
||||
function 100
|
||||
*/
|
||||
|
||||
#endif
|
||||
88
idasdk76/ldr/aif/aifcmn.cpp
Normal file
88
idasdk76/ldr/aif/aifcmn.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
static const uint32 magic1[] = { ZERO_CODE1 };
|
||||
static const uint32 magic2[] = { ZERO_CODE2 };
|
||||
static const uint32 *const magics[] = { magic1, magic2 };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_header(aif_header_t *hd)
|
||||
{
|
||||
uint32 *ptr = (uint32 *)hd;
|
||||
const int size = sizeof(aif_header_t) / sizeof(uint32);
|
||||
for ( size_t i=0; i < size; i++, ptr++ )
|
||||
*ptr = swap32(*ptr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 0-failed, 1-little endian, 2-big endian
|
||||
static int match_zero_code(aif_header_t *hd)
|
||||
{
|
||||
int mostfirst = 0;
|
||||
for ( int i=0; i < qnumber(magics); i++ )
|
||||
{
|
||||
if ( memcmp(hd->zero_code, magics[i], sizeof(hd->zero_code)) == 0 )
|
||||
return mostfirst+1;
|
||||
swap_header(hd);
|
||||
mostfirst = !mostfirst;
|
||||
if ( memcmp(hd->zero_code, magics[i], sizeof(hd->zero_code)) == 0 )
|
||||
return mostfirst+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// check input file format. if recognized, then return 1
|
||||
// otherwise return 0
|
||||
//
|
||||
bool is_aif_file(linput_t *li)
|
||||
{
|
||||
aif_header_t hd;
|
||||
qlseek(li, 0);
|
||||
if ( qlread(li, &hd, sizeof(hd)) != sizeof(hd) )
|
||||
return false;
|
||||
return match_zero_code(&hd) != 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_section(section_t *s)
|
||||
{
|
||||
s->codestart = swap32(s->codestart);
|
||||
s->datastart = swap32(s->datastart);
|
||||
s->codesize = swap32(s->codesize);
|
||||
s->datasize = swap32(s->datasize);
|
||||
s->fileinfo = swap32(s->fileinfo);
|
||||
s->debugsize = swap32(s->debugsize);
|
||||
s->name = swap32(s->name);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_dsym(dsym_t *s)
|
||||
{
|
||||
s->sym = swap32(s->sym);
|
||||
s->value = swap32(s->value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// returns true - debug info with pascal symbols
|
||||
static bool swap_symbols(dsym_t *ds, char *str, uchar *end, size_t nsyms)
|
||||
{
|
||||
int npascal = 0; // number of pascal strings
|
||||
int nc = 0; // number of c strings
|
||||
for ( int i=0; i < nsyms; i++,ds++ )
|
||||
{
|
||||
if ( is_mf() )
|
||||
swap_dsym(ds);
|
||||
if ( ds->sym & ASD_16BITSYM )
|
||||
continue;
|
||||
size_t off = size_t(ds->sym & ASD_SYMOFF);
|
||||
char *name = str + off;
|
||||
if ( name >= (char *)end )
|
||||
continue;
|
||||
if ( name[0] == strlen(name)-1 )
|
||||
npascal++;
|
||||
else
|
||||
nc++;
|
||||
}
|
||||
return npascal > nc;
|
||||
}
|
||||
|
||||
14
idasdk76/ldr/aif/makefile
Normal file
14
idasdk76/ldr/aif/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=aif
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)aif$(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 ../aof/aof.h ../idaldr.h aif.cpp aif.h \
|
||||
aifcmn.cpp
|
||||
610
idasdk76/ldr/amiga/amiga.cpp
Normal file
610
idasdk76/ldr/amiga/amiga.cpp
Normal file
@@ -0,0 +1,610 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2020 by Ilfak Guilfanov, <ig@datarescue.com>
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* AMIGA hunk file loader
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "amiga.hpp"
|
||||
|
||||
#define SkipLong(Longs) do { if ( qlseek(li, 4 * qoff64_t(Longs), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 )
|
||||
#define SkipWord(Words) do { if ( qlseek(li, 2 * qoff64_t(Words), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 )
|
||||
#define SkipByte(Bytes) do { if ( qlseek(li, 1 * qoff64_t(Bytes), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 )
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static void ask_for_help(void)
|
||||
{
|
||||
ask_for_feedback("This file contains some untested records");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static char *read_name(linput_t *li, char *buf, size_t bufsize, int Longs)
|
||||
{
|
||||
if ( ssize_t(bufsize) > 0 )
|
||||
{
|
||||
size_t sz = Longs;
|
||||
if ( sz != 0 )
|
||||
{
|
||||
sz *= 4;
|
||||
if ( sz >= bufsize )
|
||||
sz = bufsize-1;
|
||||
lread(li, buf, sz);
|
||||
}
|
||||
buf[sz] = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li,ushort /*_neflags*/,const char * /*fileformatname*/)
|
||||
{
|
||||
set_processor_type("68040", SETPROC_LOADER);
|
||||
|
||||
uint32 Type, Data, i;
|
||||
int nums;
|
||||
char NameString[MAXSTR];
|
||||
bool has_header = false;
|
||||
bool shortreloc = false;
|
||||
ea_t start = to_ea(inf_get_baseaddr(), 0);
|
||||
ea_t end = start;
|
||||
|
||||
//
|
||||
// The first pass
|
||||
//
|
||||
qoff64_t fsize = qlsize(li);
|
||||
qlseek(li, 0);
|
||||
while ( true )
|
||||
{
|
||||
i = (uint32)qlread(li, &Type, sizeof(Type));
|
||||
if ( i != sizeof(Type) )
|
||||
{
|
||||
if ( i != 0 )
|
||||
warning("There %s %u extra byte%s at end of file.",
|
||||
i == 1 ? "is" : "are",
|
||||
i,
|
||||
i == 1 ? "" : "s");
|
||||
break;
|
||||
}
|
||||
Type = swap32(Type);
|
||||
|
||||
if ( Type == HUNK_DREL32 && has_header )
|
||||
Type = HUNK_DREL32EXE;
|
||||
|
||||
switch ( Type & 0xFFFF )
|
||||
{
|
||||
case HUNK_UNIT:
|
||||
read_name(li, NameString, sizeof(NameString), mf_readlong(li));
|
||||
break;
|
||||
case HUNK_NAME:
|
||||
read_name(li, NameString, sizeof(NameString), mf_readlong(li));
|
||||
break;
|
||||
case HUNK_LIB:
|
||||
SkipLong(1);
|
||||
break;
|
||||
case HUNK_INDEX:
|
||||
SkipLong(mf_readlong(li));
|
||||
break;
|
||||
case HUNK_CODE:
|
||||
case HUNK_PPC_CODE:
|
||||
case HUNK_DATA:
|
||||
case HUNK_BSS:
|
||||
{
|
||||
Data = mf_readlong(li);
|
||||
Data <<= 2;
|
||||
Data &= 0x7FFFFFFF;
|
||||
start = free_chunk(end, Data, -0xF);
|
||||
end = start + Data;
|
||||
if ( end < start )
|
||||
loader_failure("Segment address overlow: %a..%a", start, end);
|
||||
const char *sname = NULL;
|
||||
sel_t sel = get_segm_qty() + 1;
|
||||
set_selector(sel, 0);
|
||||
switch ( Type & 0xFFFF )
|
||||
{
|
||||
case HUNK_PPC_CODE:
|
||||
set_processor_type("ppc", SETPROC_LOADER);
|
||||
sname = "PPC_CODE";
|
||||
break;
|
||||
case HUNK_CODE:
|
||||
sname = "CODE";
|
||||
if ( inf_get_start_cs() == BADSEL )
|
||||
{
|
||||
inf_set_start_cs(sel);
|
||||
inf_set_start_ip(start);
|
||||
}
|
||||
break;
|
||||
case HUNK_DATA:
|
||||
sname = "DATA";
|
||||
break;
|
||||
case HUNK_BSS:
|
||||
sname = "BSS";
|
||||
break;
|
||||
}
|
||||
if ( (Type & 0xFFFF) != HUNK_BSS )
|
||||
{
|
||||
uint64 rest = fsize - qltell(li);
|
||||
if ( end-start > rest )
|
||||
loader_failure("Too big segment %a..%a", start, end);
|
||||
file2base(li, qltell(li), start, end, FILEREG_PATCHABLE);
|
||||
}
|
||||
segment_t s;
|
||||
s.sel = setup_selector(sel);
|
||||
s.start_ea = start;
|
||||
s.end_ea = end;
|
||||
s.align = saRelByte;
|
||||
s.comb = scPub;
|
||||
s.bitness = PH.get_segm_bitness();
|
||||
add_segm_ex(&s, sname, sname, ADDSEG_NOSREG|ADDSEG_SPARSE);
|
||||
}
|
||||
break;
|
||||
case HUNK_RELOC32SHORT:
|
||||
case HUNK_DREL32EXE:
|
||||
shortreloc = true;
|
||||
// no break
|
||||
case HUNK_RELRELOC32:
|
||||
case HUNK_ABSRELOC16:
|
||||
case HUNK_RELRELOC26:
|
||||
case HUNK_RELOC32:
|
||||
case HUNK_RELOC16:
|
||||
case HUNK_RELOC8:
|
||||
case HUNK_DREL32:
|
||||
case HUNK_DREL16:
|
||||
case HUNK_DREL8:
|
||||
nums = 0;
|
||||
while ( true )
|
||||
{
|
||||
if ( qltell(li) >= fsize )
|
||||
TRUNCATED_INPUT:
|
||||
loader_failure("Truncated file");
|
||||
Data = shortreloc ? mf_readshort(li) : mf_readlong(li);
|
||||
if ( Data == 0 )
|
||||
break;
|
||||
shortreloc ? mf_readshort(li) : mf_readlong(li);
|
||||
if ( shortreloc )
|
||||
SkipWord(Data);
|
||||
else
|
||||
SkipLong(Data);
|
||||
nums += Data;
|
||||
}
|
||||
if ( (nums & 1) == 0 && shortreloc )
|
||||
SkipWord(1);
|
||||
shortreloc = false;
|
||||
break;
|
||||
case HUNK_EXT:
|
||||
while ( true )
|
||||
{
|
||||
if ( qltell(li) >= fsize )
|
||||
goto TRUNCATED_INPUT;
|
||||
Data = mf_readlong(li);
|
||||
if ( Data == 0 )
|
||||
break;
|
||||
/* Is it followed by a symbol name? */
|
||||
if ( Data & 0xFFFFFF )
|
||||
read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF);
|
||||
|
||||
/* Remember extension type. */
|
||||
int32 exttype = (Data >> 24) & 0xFF;
|
||||
|
||||
/* Display value of symbol. */
|
||||
if ( exttype == EXT_DEF || exttype == EXT_ABS || exttype == EXT_RES )
|
||||
mf_readlong(li);
|
||||
|
||||
/* Skip relocation information. */
|
||||
if ( exttype == EXT_REF32
|
||||
|| exttype == EXT_REF16
|
||||
|| exttype == EXT_REF8
|
||||
// || exttype == EXT_DEXT32
|
||||
// || exttype == EXT_DEXT16
|
||||
// || exttype == EXT_DEXT8
|
||||
// || exttype == EXT_RELREF32
|
||||
|| exttype == EXT_RELREF26 )
|
||||
{
|
||||
SkipLong(mf_readlong(li));
|
||||
}
|
||||
|
||||
/* Display size of common block. */
|
||||
if ( exttype == EXT_COMMON )
|
||||
{
|
||||
mf_readlong(li);
|
||||
SkipLong(mf_readlong(li));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HUNK_SYMBOL:
|
||||
while ( true )
|
||||
{
|
||||
if ( qltell(li) >= fsize )
|
||||
goto TRUNCATED_INPUT;
|
||||
Data = mf_readlong(li);
|
||||
if ( Data == 0 )
|
||||
break;
|
||||
read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF);
|
||||
mf_readlong(li);
|
||||
}
|
||||
break;
|
||||
case HUNK_DEBUG:
|
||||
SkipLong(mf_readlong(li));
|
||||
break;
|
||||
case HUNK_END:
|
||||
break;
|
||||
case HUNK_HEADER:
|
||||
{
|
||||
has_header = true;
|
||||
while ( true )
|
||||
{
|
||||
if ( qltell(li) >= fsize )
|
||||
goto TRUNCATED_INPUT;
|
||||
Data = mf_readlong(li);
|
||||
if ( Data == 0 )
|
||||
break;
|
||||
read_name(li, NameString, sizeof(NameString), Data);
|
||||
}
|
||||
mf_readlong(li);
|
||||
int32 From = mf_readlong(li);
|
||||
int32 To = mf_readlong(li);
|
||||
SkipLong(To-From+1);
|
||||
}
|
||||
break;
|
||||
case HUNK_OVERLAY:
|
||||
{
|
||||
int32 TabSize = mf_readlong(li);
|
||||
if ( TabSize )
|
||||
{
|
||||
mf_readlong(li);
|
||||
SkipLong(TabSize);
|
||||
}
|
||||
int32 hunktype = mf_readlong(li);
|
||||
if ( TabSize && hunktype >= HUNK_UNIT && hunktype <= HUNK_ABSRELOC16 )
|
||||
qlseek(li, -4, SEEK_CUR);
|
||||
}
|
||||
break;
|
||||
case HUNK_BREAK:
|
||||
break;
|
||||
default:
|
||||
warning("Unknown hunk type %04X - Aborting!", Type & 0xFFFF);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The second pass
|
||||
//
|
||||
qlseek(li, 0);
|
||||
int nseg = 0;
|
||||
while ( true )
|
||||
{
|
||||
i = (uint32)qlread(li, &Type, sizeof(Type));
|
||||
if ( i != sizeof(Type) )
|
||||
break;
|
||||
Type = swap32(Type);
|
||||
|
||||
if ( Type == HUNK_DREL32 && has_header )
|
||||
Type = HUNK_DREL32EXE;
|
||||
|
||||
switch ( Type & 0xFFFF )
|
||||
{
|
||||
case HUNK_UNIT:
|
||||
read_name(li, NameString, sizeof(NameString), mf_readlong(li));
|
||||
add_pgm_cmt("Unit: %s", NameString);
|
||||
break;
|
||||
case HUNK_NAME:
|
||||
read_name(li, NameString, sizeof(NameString), mf_readlong(li));
|
||||
add_pgm_cmt("Title: %s", NameString);
|
||||
break;
|
||||
case HUNK_LIB:
|
||||
mf_readlong(li);
|
||||
break;
|
||||
case HUNK_INDEX:
|
||||
SkipLong(mf_readlong(li));
|
||||
break;
|
||||
case HUNK_CODE:
|
||||
case HUNK_PPC_CODE:
|
||||
case HUNK_DATA:
|
||||
case HUNK_BSS:
|
||||
Data = mf_readlong(li);
|
||||
Data <<= 2;
|
||||
Data &= 0x7FFFFFFF;
|
||||
if ( (Type & 0xFFFF) != HUNK_BSS )
|
||||
SkipByte(Data);
|
||||
nseg++;
|
||||
break;
|
||||
case HUNK_RELOC32SHORT:
|
||||
case HUNK_DREL32EXE:
|
||||
shortreloc = true;
|
||||
// no break
|
||||
case HUNK_RELRELOC32:
|
||||
case HUNK_ABSRELOC16:
|
||||
case HUNK_RELRELOC26:
|
||||
case HUNK_RELOC32:
|
||||
case HUNK_RELOC16:
|
||||
case HUNK_RELOC8:
|
||||
case HUNK_DREL32:
|
||||
case HUNK_DREL16:
|
||||
case HUNK_DREL8:
|
||||
nums = 0;
|
||||
while ( (Data=(shortreloc ? mf_readshort(li) : mf_readlong(li))) != 0 )
|
||||
{
|
||||
uint32 dat2 = shortreloc ? mf_readshort(li) : mf_readlong(li);
|
||||
segment_t *s = get_segm_by_sel(dat2+1);
|
||||
segment_t *ssrc = get_segm_by_sel(nseg);
|
||||
ea_t base = BADADDR;
|
||||
if ( ssrc != NULL )
|
||||
base = ssrc->start_ea;
|
||||
else
|
||||
s = NULL;
|
||||
int elsize = shortreloc ? 2 : 4;
|
||||
validate_array_count_or_die(li, Data, elsize, "Number of relocations");
|
||||
for ( uint32 dat3 = Data; dat3; --dat3 )
|
||||
{
|
||||
uint32 off = shortreloc ? mf_readshort(li) : mf_readlong(li);
|
||||
if ( s != NULL )
|
||||
{
|
||||
ea_t src = base + off;
|
||||
ea_t dst = s->start_ea;
|
||||
ea_t target = BADADDR;
|
||||
fixup_type_t fd_type = 0;
|
||||
switch ( Type & 0xFFFF )
|
||||
{
|
||||
case HUNK_RELRELOC32:
|
||||
case HUNK_RELOC32:
|
||||
case HUNK_DREL32:
|
||||
case HUNK_RELOC32SHORT:
|
||||
case HUNK_DREL32EXE:
|
||||
target = get_dword(src)+dst;
|
||||
put_dword(src, target);
|
||||
fd_type = FIXUP_OFF32;
|
||||
break;
|
||||
case HUNK_ABSRELOC16:
|
||||
case HUNK_RELRELOC26:
|
||||
case HUNK_RELOC16:
|
||||
case HUNK_DREL16:
|
||||
target = get_word(src)+dst;
|
||||
put_word(src, target);
|
||||
fd_type = FIXUP_OFF16;
|
||||
break;
|
||||
case HUNK_RELOC8:
|
||||
case HUNK_DREL8:
|
||||
target = get_byte(src)+dst;
|
||||
put_byte(src, (uint32)target);
|
||||
fd_type = FIXUP_OFF8;
|
||||
break;
|
||||
}
|
||||
if ( fd_type != 0 )
|
||||
{
|
||||
fixup_data_t fd(fd_type);
|
||||
fd.sel = dat2 + 1;
|
||||
fd.off = target;
|
||||
fd.set(src);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ask_for_help();
|
||||
}
|
||||
}
|
||||
nums += Data;
|
||||
}
|
||||
if ( (nums & 1) == 0 && shortreloc )
|
||||
SkipWord(1);
|
||||
shortreloc = false;
|
||||
break;
|
||||
case HUNK_EXT:
|
||||
ask_for_help();
|
||||
while ( (Data=mf_readlong(li)) != 0 )
|
||||
{
|
||||
switch ( (Data >> 24) & 0xFF )
|
||||
{
|
||||
case EXT_DEF: msg(" EXT_DEF"); break;
|
||||
case EXT_ABS: msg(" EXT_ABS"); break;
|
||||
case EXT_RES: msg(" EXT_RES"); break;
|
||||
case EXT_REF32: msg(" EXT_REF32"); break;
|
||||
case EXT_COMMON: msg(" EXT_COMMON"); break;
|
||||
case EXT_REF16: msg(" EXT_REF16"); break;
|
||||
case EXT_REF8: msg(" EXT_REF8"); break;
|
||||
// case EXT_DEXT32: msg(" EXT_DEXT32"); break;
|
||||
// case EXT_DEXT16: msg(" EXT_DEXT16"); break;
|
||||
// case EXT_DEXT8: msg(" EXT_DEXT8"); break;
|
||||
// case EXT_RELREF32: msg(" EXT_RELREF32"); break;
|
||||
// case EXT_RELREF26: msg(" EXT_RELREF26"); break;
|
||||
// case EXT_RELCOMMON: msg(" EXT_RELCOMMON"); break;
|
||||
default: msg(" EXT_??? (%02x)\n",(Data >> 24) & 0xFF); break;
|
||||
}
|
||||
|
||||
/* Is it followed by a symbol name? */
|
||||
|
||||
if ( Data & 0xFFFFFF )
|
||||
{
|
||||
read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF);
|
||||
msg(" %s", NameString);
|
||||
}
|
||||
|
||||
/* Remember extension type. */
|
||||
int32 exttype = (Data >> 24) & 0xFF;
|
||||
|
||||
/* Display value of symbol. */
|
||||
if ( exttype == EXT_DEF || exttype == EXT_ABS || exttype == EXT_RES )
|
||||
{
|
||||
if ( !(Data & 0xFFFFFF) )
|
||||
msg(" ???");
|
||||
|
||||
Data = mf_readlong(li);
|
||||
msg("%08X", Data);
|
||||
}
|
||||
|
||||
/* Skip relocation information. */
|
||||
if ( exttype == EXT_REF32
|
||||
|| exttype == EXT_REF16
|
||||
|| exttype == EXT_REF8
|
||||
// || exttype == EXT_DEXT32
|
||||
// || exttype == EXT_DEXT16
|
||||
// || exttype == EXT_DEXT8
|
||||
// || exttype == EXT_RELREF32
|
||||
|| exttype == EXT_RELREF26 )
|
||||
{
|
||||
Data = mf_readlong(li);
|
||||
msg("= %u entr%s", Data, Data == 1 ? "y" : "ies");
|
||||
SkipLong(Data);
|
||||
}
|
||||
|
||||
/* Display size of common block. */
|
||||
if ( exttype == EXT_COMMON )
|
||||
{
|
||||
Data = mf_readlong(li);
|
||||
|
||||
msg(" Size = %u bytes", Data << 2);
|
||||
Data = mf_readlong(li);
|
||||
SkipLong(Data);
|
||||
}
|
||||
msg("\n");
|
||||
}
|
||||
break;
|
||||
case HUNK_SYMBOL:
|
||||
while ( (Data=mf_readlong(li)) != 0 )
|
||||
{
|
||||
/* Display name. */
|
||||
read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF);
|
||||
|
||||
/* Display value. */
|
||||
Data = mf_readlong(li);
|
||||
|
||||
segment_t *ssrc = get_segm_by_sel(nseg);
|
||||
if ( ssrc == NULL )
|
||||
ask_for_help();
|
||||
else
|
||||
set_name(ssrc->start_ea+Data, NameString, SN_NOCHECK | SN_NOWARN | SN_IDBENC);
|
||||
}
|
||||
break;
|
||||
case HUNK_DEBUG:
|
||||
SkipLong(mf_readlong(li));
|
||||
break;
|
||||
case HUNK_END:
|
||||
break;
|
||||
case HUNK_HEADER:
|
||||
{
|
||||
has_header = true;
|
||||
while ( (Data=mf_readlong(li)) != 0 )
|
||||
read_name(li, NameString, sizeof(NameString), Data);
|
||||
mf_readlong(li);
|
||||
int32 From = mf_readlong(li);
|
||||
int32 To = mf_readlong(li);
|
||||
SkipLong(To-From+1);
|
||||
}
|
||||
break;
|
||||
case HUNK_OVERLAY:
|
||||
{
|
||||
int32 TabSize = mf_readlong(li);
|
||||
if ( TabSize )
|
||||
{
|
||||
mf_readlong(li);
|
||||
SkipLong(TabSize);
|
||||
}
|
||||
int32 hunktype = mf_readlong(li);
|
||||
if ( TabSize && hunktype >= HUNK_UNIT && hunktype <= HUNK_ABSRELOC16 )
|
||||
qlseek(li, -4, SEEK_CUR);
|
||||
}
|
||||
break;
|
||||
case HUNK_BREAK:
|
||||
break;
|
||||
default:
|
||||
warning("Unknown hunk type %04X - Aborting!", Type & 0xFFFF);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
create_filename_cmt();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
qlseek(li, 0);
|
||||
uint32 type;
|
||||
if ( qlread(li, &type, sizeof(uint32)) == sizeof(uint32)
|
||||
&& swap32(type) == HUNK_HEADER )
|
||||
{
|
||||
*fileformatname = "Amiga hunk file";
|
||||
*processor = "68040";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int idaapi move_segm_relocs(ea_t from, ea_t to, asize_t size, const char *fileformatname)
|
||||
{
|
||||
qnotused(size);
|
||||
qnotused(fileformatname);
|
||||
if ( from == BADADDR )
|
||||
{
|
||||
// The entire program is being rebased.
|
||||
// In this case, 'to' actually contains a delta value; the number of bytes
|
||||
// forward (positive) or backward (negative) that the whole database is
|
||||
// being moved.
|
||||
ea_t delta = to;
|
||||
|
||||
// fix up relocations
|
||||
fixup_data_t fd;
|
||||
|
||||
for ( ea_t xEA = get_first_fixup_ea(); xEA != BADADDR; xEA = get_next_fixup_ea(xEA) )
|
||||
{
|
||||
show_addr(xEA);
|
||||
|
||||
get_fixup(&fd, xEA);
|
||||
fd.off += delta;
|
||||
|
||||
switch ( fd.get_type() )
|
||||
{
|
||||
case FIXUP_OFF8:
|
||||
put_byte(xEA, fd.off);
|
||||
break;
|
||||
case FIXUP_OFF16:
|
||||
put_word(xEA, fd.off);
|
||||
break;
|
||||
case FIXUP_OFF32:
|
||||
put_dword(xEA, fd.off);
|
||||
break;
|
||||
}
|
||||
|
||||
set_fixup(xEA, fd);
|
||||
}
|
||||
|
||||
// Record the new image base address.
|
||||
inf_set_baseaddr(inf_get_baseaddr() + delta);
|
||||
// set_imagebase(new_base);
|
||||
}
|
||||
|
||||
return 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,
|
||||
// take care of a moved segment (fix up relocations, for example)
|
||||
move_segm_relocs,
|
||||
NULL,
|
||||
};
|
||||
59
idasdk76/ldr/amiga/amiga.hpp
Normal file
59
idasdk76/ldr/amiga/amiga.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2000 by Ilfak Guilfanov, <ig@datarescue.com>
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// AMIGA hunk files
|
||||
//
|
||||
|
||||
#ifndef AMIGA_HPP
|
||||
#define AMIGA_HPP
|
||||
|
||||
#define HUNK_UNIT 999
|
||||
#define HUNK_NAME 1000
|
||||
#define HUNK_CODE 1001
|
||||
#define HUNK_DATA 1002
|
||||
#define HUNK_BSS 1003
|
||||
#define HUNK_RELOC32 1004
|
||||
#define HUNK_RELOC16 1005
|
||||
#define HUNK_RELOC8 1006
|
||||
#define HUNK_EXT 1007
|
||||
#define HUNK_SYMBOL 1008
|
||||
#define HUNK_DEBUG 1009
|
||||
#define HUNK_END 1010
|
||||
#define HUNK_HEADER 1011
|
||||
#define HUNK_UNUSED 1012 // unused hunk number?
|
||||
#define HUNK_OVERLAY 1013
|
||||
#define HUNK_BREAK 1014
|
||||
#define HUNK_DREL32 1015
|
||||
#define HUNK_DREL16 1016
|
||||
#define HUNK_DREL8 1017
|
||||
#define HUNK_LIB 1018
|
||||
#define HUNK_INDEX 1019
|
||||
#define HUNK_RELOC32SHORT 1020
|
||||
#define HUNK_RELRELOC32 1021
|
||||
#define HUNK_ABSRELOC16 1022
|
||||
#define HUNK_DREL32EXE 1023
|
||||
|
||||
#define HUNK_PPC_CODE 1257
|
||||
#define HUNK_RELRELOC26 1260
|
||||
#define EXT_RELREF26 229
|
||||
|
||||
// i don't know the values! (these symbols are used with HUNK_CODE, _DATA, _BSS)
|
||||
#define HUNKF_CHIP 0x00000000
|
||||
#define HUNKF_FAST 0x00000000
|
||||
#define HUNKF_ADVISORY 0x00000000
|
||||
|
||||
#define EXT_SYMB 0
|
||||
#define EXT_DEF 1
|
||||
#define EXT_ABS 2
|
||||
#define EXT_RES 3
|
||||
#define EXT_REF32 129
|
||||
#define EXT_COMMON 130
|
||||
#define EXT_REF16 131
|
||||
#define EXT_REF8 132
|
||||
|
||||
#endif // AMIGA_HPP
|
||||
13
idasdk76/ldr/amiga/makefile
Normal file
13
idasdk76/ldr/amiga/makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
PROC=amiga
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)amiga$(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 ../idaldr.h amiga.cpp amiga.hpp
|
||||
724
idasdk76/ldr/aof/aof.cpp
Normal file
724
idasdk76/ldr/aof/aof.cpp
Normal file
@@ -0,0 +1,724 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-97 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
* ARM Object File Loader
|
||||
* ----------------------
|
||||
* This module allows IDA to load ARM object files into
|
||||
* its database and to disassemble them correctly.
|
||||
*
|
||||
* NOTE 1: for the moment only B/BL instruction relocations are
|
||||
* supported. I cannot find other relocation examples so
|
||||
* they are not implemented yet.
|
||||
*
|
||||
* NOTE 2: Thumb modules are not supported.
|
||||
*
|
||||
* This module automatically detects the byte sex and sets inf.mf
|
||||
* variable accrodingly.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "aof.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
NORETURN static void nomem(void)
|
||||
{
|
||||
nomem("AOF loader");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void *read_chunk(linput_t *li, const chunk_entry_t &ce)
|
||||
{
|
||||
void *chunk = qalloc_array<char>(ce.size);
|
||||
if ( chunk == NULL )
|
||||
nomem();
|
||||
qlseek(li, ce.file_offset);
|
||||
lread(li, chunk, ce.size);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void check_chunk_ptr(
|
||||
const chunk_entry_t &ce,
|
||||
const void *chunkstart,
|
||||
const void *chunkptr,
|
||||
size_t ptrsize)
|
||||
{
|
||||
const char *p0 = (const char*)chunkstart;
|
||||
const char *p1 = (const char*)chunkptr;
|
||||
if ( p1 < p0 || p1 + ptrsize < p0 || (p1 + ptrsize - p0) > ce.size )
|
||||
loader_failure("Corrupted file");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void check_chunk_str(
|
||||
const chunk_entry_t &ce,
|
||||
const void *chunkstart,
|
||||
const void *chunkptr)
|
||||
{
|
||||
const char *p0 = (const char*)chunkstart;
|
||||
const char *p1 = (const char*)chunkptr;
|
||||
if ( p1 >= p0 )
|
||||
{
|
||||
const char *chunk_end = p0 + ce.size;
|
||||
while ( p1 < chunk_end )
|
||||
{
|
||||
if ( *p1 == '\0' )
|
||||
return;
|
||||
++p1;
|
||||
}
|
||||
}
|
||||
loader_failure("Corrupted file");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *)
|
||||
{
|
||||
chunk_header_t hd;
|
||||
if ( qlread(li, &hd, sizeof(hd)) != sizeof(hd) )
|
||||
return 0;
|
||||
if ( hd.ChunkFileId != AOF_MAGIC && hd.ChunkFileId != AOF_MAGIC_B )
|
||||
return 0;
|
||||
if ( hd.num_chunks > hd.max_chunks )
|
||||
return 0;
|
||||
|
||||
*fileformatname = "ARM Object File";
|
||||
*processor = "arm";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create32(
|
||||
sel_t sel,
|
||||
ea_t start_ea,
|
||||
ea_t end_ea,
|
||||
const char *name,
|
||||
const char *classname)
|
||||
{
|
||||
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 = scPub;
|
||||
s.bitness = 1; // 32-bit
|
||||
|
||||
if ( !add_segm_ex(&s, name, classname, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static ea_t get_area_base(int idx)
|
||||
{
|
||||
segment_t *s = get_segm_by_sel(idx+1);
|
||||
if ( s == NULL )
|
||||
return BADADDR;
|
||||
return s->start_ea;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static ea_t find_area(
|
||||
const chunk_entry_t &ce,
|
||||
const area_header_t *ah,
|
||||
int maxarea,
|
||||
const char *strings,
|
||||
const char *areaname)
|
||||
{
|
||||
for ( int i=0; i < maxarea; i++, ah++ )
|
||||
{
|
||||
const char *name = strings + size_t(ah->name);
|
||||
check_chunk_str(ce, strings, name);
|
||||
if ( streq(name, areaname) )
|
||||
return get_area_base(i);
|
||||
}
|
||||
return BADADDR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static ea_t create_spec_seg(
|
||||
int *nsegs,
|
||||
int nelem,
|
||||
const char *name,
|
||||
uchar seg_type)
|
||||
{
|
||||
ea_t ea = BADADDR;
|
||||
if ( nelem != 0 )
|
||||
{
|
||||
nelem *= 4;
|
||||
ea = free_chunk(inf_get_max_ea(), nelem, 0xFFF);
|
||||
(*nsegs)++;
|
||||
create32(*nsegs, ea, ea+nelem, name, CLASS_DATA);
|
||||
segment_t *s = getseg(ea);
|
||||
s->type = seg_type;
|
||||
s->update();
|
||||
set_arm_segm_flags(s->start_ea, 2 << SEGFL_SHIFT); // alignment
|
||||
}
|
||||
return ea;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void process_name(ea_t ea, const char *name, uint32 flags, bool iscode)
|
||||
{
|
||||
// ignore aux names -- they hinder data creation
|
||||
if ( strstr(name, "$litpool_e$") != NULL )
|
||||
return;
|
||||
if ( flags & SF_PUB )
|
||||
{
|
||||
add_entry(ea, ea, name, iscode, AEF_IDBENC);
|
||||
make_name_public(ea);
|
||||
}
|
||||
else
|
||||
{
|
||||
force_name(ea, name, SN_IDBENC);
|
||||
}
|
||||
if ( flags & SF_WEAK )
|
||||
make_name_weak(ea);
|
||||
if ( flags & SF_ICASE )
|
||||
add_extra_cmt(ea, true, "Case-insensitive label");
|
||||
if ( flags & SF_STRNG )
|
||||
add_extra_cmt(ea, true, "Strong name");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void reloc_insn(ea_t ea, uint32 rvalue, uint32 type)
|
||||
{
|
||||
uint32 code = get_dword(ea);
|
||||
switch ( (code >> 24) & 0xF )
|
||||
{
|
||||
case 0x0A: // B
|
||||
case 0x0B: // BL
|
||||
{
|
||||
int32 off = code & 0x00FFFFFFL;
|
||||
if ( off & 0x00800000L )
|
||||
off |= ~0x00FFFFFFL; // extend sign
|
||||
off <<= 2;
|
||||
off += rvalue;
|
||||
off >>= 2;
|
||||
off &= 0xFFFFFFL;
|
||||
code &= 0xFF000000L;
|
||||
code |= off;
|
||||
put_dword(ea, code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("This relocation type is not implemented yet\n"
|
||||
"\3%a: reloc insn rvalue=%x, rt=%lx", ea, rvalue,
|
||||
type & RF_II);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void swap_chunk_entry(chunk_entry_t *ce)
|
||||
{
|
||||
ce->file_offset = swap32(ce->file_offset);
|
||||
ce->size = swap32(ce->size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_aof_header(aof_header_t *ahd)
|
||||
{
|
||||
ahd->obj_file_type = swap32(ahd->obj_file_type);
|
||||
ahd->version = swap32(ahd->version);
|
||||
ahd->num_areas = swap32(ahd->num_areas);
|
||||
ahd->num_syms = swap32(ahd->num_syms);
|
||||
ahd->entry_area = swap32(ahd->entry_area);
|
||||
ahd->entry_offset = swap32(ahd->entry_offset);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_area_header(area_header_t *ah)
|
||||
{
|
||||
ah->name = swap32(ah->name);
|
||||
ah->flags = swap32(ah->flags);
|
||||
ah->size = swap32(ah->size);
|
||||
ah->num_relocs = swap32(ah->num_relocs);
|
||||
ah->baseaddr = swap32(ah->baseaddr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void swap_sym(sym_t *s)
|
||||
{
|
||||
s->name = swap32(s->name);
|
||||
s->flags = swap32(s->flags);
|
||||
s->value = swap32(s->value);
|
||||
s->area = swap32(s->area);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
int i;
|
||||
chunk_header_t hd;
|
||||
set_processor_type("arm", SETPROC_LOADER);
|
||||
lread(li, &hd, sizeof(hd));
|
||||
if ( hd.ChunkFileId == AOF_MAGIC_B ) // BIG ENDIAN
|
||||
{
|
||||
inf_set_be(true);
|
||||
hd.max_chunks = swap32(hd.max_chunks);
|
||||
hd.num_chunks = swap32(hd.num_chunks);
|
||||
}
|
||||
|
||||
validate_array_count_or_die(li, hd.max_chunks, sizeof(chunk_entry_t), "Number of chunks");
|
||||
chunk_entry_t *ce = qalloc_array<chunk_entry_t>(size_t(hd.max_chunks));
|
||||
if ( ce == NULL )
|
||||
nomem();
|
||||
lread(li, ce, sizeof(chunk_entry_t)*size_t(hd.max_chunks));
|
||||
if ( inf_is_be() )
|
||||
for ( i=0; i < hd.max_chunks; i++ )
|
||||
swap_chunk_entry(ce+i);
|
||||
|
||||
int head = -1; // AOF Header
|
||||
int area = -1; // Areas
|
||||
int idfn = -1; // Identification
|
||||
int symt = -1; // Symbol Table
|
||||
int strt = -1; // String Table
|
||||
|
||||
for ( i=0; i < hd.max_chunks; i++ )
|
||||
{
|
||||
if ( ce[i].file_offset == 0 )
|
||||
continue;
|
||||
if ( strneq(ce[i].chunkId, OBJ_HEAD, sizeof(ce[i].chunkId)) )
|
||||
head = i;
|
||||
if ( strneq(ce[i].chunkId, OBJ_AREA, sizeof(ce[i].chunkId)) )
|
||||
area = i;
|
||||
if ( strneq(ce[i].chunkId, OBJ_IDFN, sizeof(ce[i].chunkId)) )
|
||||
idfn = i;
|
||||
if ( strneq(ce[i].chunkId, OBJ_SYMT, sizeof(ce[i].chunkId)) )
|
||||
symt = i;
|
||||
if ( strneq(ce[i].chunkId, OBJ_STRT, sizeof(ce[i].chunkId)) )
|
||||
strt = i;
|
||||
}
|
||||
if ( head == -1 || area == -1 || strt == -1 || symt == -1 || idfn == -1 )
|
||||
{
|
||||
qfree(ce);
|
||||
loader_failure("One of required chunks is missing");
|
||||
}
|
||||
|
||||
char *strings = (char *)read_chunk(li, ce[strt]);
|
||||
aof_header_t *ahd = (aof_header_t *)read_chunk(li, ce[head]);
|
||||
check_chunk_ptr(ce[head], ahd, ahd, sizeof(aof_header_t));
|
||||
if ( inf_is_be() )
|
||||
swap_aof_header(ahd);
|
||||
|
||||
//
|
||||
// Areas
|
||||
//
|
||||
|
||||
area_header_t *ah = (area_header_t *)(ahd + 1);
|
||||
if ( inf_is_be() )
|
||||
{
|
||||
for ( i=0; i < ahd->num_areas; i++ )
|
||||
{
|
||||
check_chunk_ptr(ce[head], ahd, ah+i, sizeof(area_header_t));
|
||||
swap_area_header(ah+i);
|
||||
}
|
||||
}
|
||||
qoff64_t offset = ce[area].file_offset;
|
||||
inf_set_specsegs(inf_is_64bit() ? 8 : 4);
|
||||
ea_t ea = to_ea(inf_get_baseaddr(), 0);
|
||||
for ( i=0; i < ahd->num_areas; i++, ah++ )
|
||||
{
|
||||
check_chunk_ptr(ce[head], ahd, ah, sizeof(area_header_t));
|
||||
if ( ah->flags & AREA_DEBUG )
|
||||
{
|
||||
offset += ah->size;
|
||||
offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t);
|
||||
continue;
|
||||
}
|
||||
if ( ah->flags & AREA_ABS )
|
||||
{
|
||||
ea = ah->baseaddr;
|
||||
if ( free_chunk(ea, ah->size, 1) != ea )
|
||||
error("Cannot allocate area at %a", ea);
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = free_chunk(ea, ah->size, 0xFFF);
|
||||
}
|
||||
if ( (ah->flags & AREA_BSS) == 0 )
|
||||
{
|
||||
ea_t end = ea + ah->size;
|
||||
uint64 fsize = qlsize(li);
|
||||
if ( offset > fsize
|
||||
|| fsize-offset < ah->size
|
||||
|| end < ea )
|
||||
{
|
||||
loader_failure("Corrupted file");
|
||||
}
|
||||
file2base(li, offset, ea, end, FILEREG_PATCHABLE);
|
||||
offset += ah->size;
|
||||
}
|
||||
const char *name = strings + size_t(ah->name);
|
||||
check_chunk_str(ce[strt], strings, name);
|
||||
const char *classname;
|
||||
if ( ah->flags & AREA_CODE )
|
||||
classname = CLASS_CODE;
|
||||
else if ( ah->flags & (AREA_BSS|AREA_COMREF) )
|
||||
classname = CLASS_BSS;
|
||||
else
|
||||
classname = CLASS_DATA;
|
||||
create32(i+1, ea, ea+ah->size, name, classname);
|
||||
|
||||
segment_t *s = getseg(ea);
|
||||
ushort sflags = (ah->flags & 0x1F) << SEGFL_SHIFT; // alignment
|
||||
if ( ah->flags & AREA_BASED )
|
||||
sflags |= (SEGFL_BASED|ah->get_based_reg());
|
||||
if ( ah->flags & AREA_PIC )
|
||||
sflags |= SEGFL_PIC;
|
||||
if ( ah->flags & AREA_REENTR )
|
||||
sflags |= SEGFL_REENTR;
|
||||
if ( ah->flags & AREA_HALFW )
|
||||
sflags |= SEGFL_HALFW;
|
||||
if ( ah->flags & AREA_INTER )
|
||||
sflags |= SEGFL_INTER;
|
||||
if ( ah->flags & AREA_COMMON )
|
||||
sflags |= SEGFL_COMDEF;
|
||||
if ( ah->flags & (AREA_COMMON|AREA_COMREF) )
|
||||
s->comb = scCommon;
|
||||
if ( ah->flags & AREA_RDONLY )
|
||||
s->perm = SEGPERM_READ;
|
||||
if ( ah->flags & AREA_ABS )
|
||||
s->align = saAbs;
|
||||
s->update();
|
||||
set_arm_segm_flags(s->start_ea, sflags);
|
||||
|
||||
if ( i == 0 )
|
||||
{
|
||||
create_filename_cmt();
|
||||
char *id = (char *)read_chunk(li, ce[idfn]);
|
||||
check_chunk_str(ce[idfn], id, id);
|
||||
add_pgm_cmt("Translator : %s", id);
|
||||
qfree(id);
|
||||
}
|
||||
|
||||
if ( ah->flags & AREA_CODE )
|
||||
{
|
||||
if ( (ah->flags & AREA_32BIT) == 0 )
|
||||
add_pgm_cmt("The 26-bit area");
|
||||
if ( (ah->flags & AREA_EXTFP) != 0 )
|
||||
add_pgm_cmt("Extended FP instructions are used");
|
||||
if ( (ah->flags & AREA_NOCHK) != 0 )
|
||||
add_pgm_cmt("No Software Stack Check");
|
||||
if ( (ah->flags & AREA_THUMB) != 0 )
|
||||
add_pgm_cmt("Thumb code area");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (ah->flags & AREA_SHARED) != 0 )
|
||||
add_pgm_cmt("Shared Library Stub Data");
|
||||
}
|
||||
ea += ah->size;
|
||||
offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t);
|
||||
}
|
||||
int nsegs = i;
|
||||
|
||||
//
|
||||
// Symbol Table
|
||||
//
|
||||
|
||||
ah = (area_header_t *)(ahd + 1);
|
||||
uint32 *delta = qalloc_array<uint32>(size_t(ahd->num_syms));
|
||||
if ( delta == NULL )
|
||||
nomem();
|
||||
memset(delta, 0, sizeof(uint32)*size_t(ahd->num_syms));
|
||||
sym_t *syms = (sym_t *)read_chunk(li, ce[symt]);
|
||||
if ( inf_is_be() )
|
||||
{
|
||||
for ( i=0; i < ahd->num_syms; i++ )
|
||||
{
|
||||
check_chunk_ptr(ce[symt], syms, syms+i, sizeof(sym_t));
|
||||
swap_sym(syms+i);
|
||||
}
|
||||
}
|
||||
int n_undef = 0;
|
||||
int n_abs = 0;
|
||||
int n_comm = 0;
|
||||
|
||||
for ( i=0; i < ahd->num_syms; i++ )
|
||||
{
|
||||
sym_t *s = syms + i;
|
||||
check_chunk_ptr(ce[symt], syms, syms+i, sizeof(sym_t));
|
||||
if ( s->flags & SF_DEF )
|
||||
{
|
||||
if ( s->flags & SF_ABS )
|
||||
{
|
||||
n_abs++;
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *areaname = strings + size_t(s->area);
|
||||
check_chunk_str(ce[strt], strings, areaname);
|
||||
ea_t areabase = find_area(ce[strt], ah, size_t(ahd->num_areas), strings, areaname);
|
||||
delta[i] = (uint32)areabase;
|
||||
ea_t symea = areabase + s->value;
|
||||
const char *name = strings + size_t(s->name);
|
||||
check_chunk_str(ce[strt], strings, name);
|
||||
if ( s->value == 0 && strcmp(areaname, name) == 0 )
|
||||
continue; // HACK!
|
||||
process_name(symea, name, s->flags, segtype(areabase) == SEG_CODE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (s->flags & SF_PUB) && (s->flags & SF_COMM) ) // ref to common
|
||||
n_comm++;
|
||||
else
|
||||
n_undef++;
|
||||
}
|
||||
}
|
||||
|
||||
ea_t abs_ea = create_spec_seg(&nsegs, n_abs, NAME_ABS, SEG_ABSSYM);
|
||||
ea_t undef_ea = create_spec_seg(&nsegs, n_undef, NAME_UNDEF, SEG_XTRN);
|
||||
ea_t comm_ea = create_spec_seg(&nsegs, n_comm, NAME_COMMON, SEG_COMM);
|
||||
if ( n_abs+n_undef+n_comm != 0 )
|
||||
{
|
||||
for ( i=0; i < ahd->num_syms; i++ )
|
||||
{
|
||||
sym_t *s = syms + i;
|
||||
const char *name = strings + size_t(s->name);
|
||||
check_chunk_str(ce[strt], strings, name);
|
||||
if ( s->flags & SF_DEF )
|
||||
{
|
||||
if ( s->flags & SF_ABS )
|
||||
{
|
||||
if ( inf_get_specsegs() == 8 )
|
||||
{
|
||||
put_qword(abs_ea, s->value);
|
||||
create_qword(abs_ea, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
put_dword(abs_ea, s->value);
|
||||
create_dword(abs_ea, 4);
|
||||
}
|
||||
process_name(abs_ea, name, s->flags, false);
|
||||
delta[i] = s->value;
|
||||
s->value = uint32(abs_ea - delta[i]);
|
||||
abs_ea += inf_get_specsegs();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (s->flags & SF_PUB) && (s->flags & SF_COMM) ) // ref to common
|
||||
{
|
||||
if ( inf_get_specsegs() == 8 )
|
||||
put_qword(comm_ea, s->value);
|
||||
else
|
||||
put_dword(comm_ea, s->value);
|
||||
process_name(comm_ea, name, s->flags, false);
|
||||
delta[i] = (uint32)comm_ea;
|
||||
comm_ea += inf_get_specsegs();
|
||||
}
|
||||
else
|
||||
{
|
||||
put_dword(undef_ea, 0xE1A0F00E); // RET
|
||||
process_name(undef_ea, name, s->flags, false);
|
||||
delta[i] = (uint32)undef_ea;
|
||||
undef_ea += inf_get_specsegs();
|
||||
}
|
||||
s->value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Relocations
|
||||
//
|
||||
|
||||
offset = ce[area].file_offset;
|
||||
for ( i=0; i < ahd->num_areas; i++, ah++ )
|
||||
{
|
||||
if ( ah->flags & AREA_DEBUG )
|
||||
{
|
||||
offset += ah->size;
|
||||
offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t);
|
||||
continue;
|
||||
}
|
||||
if ( (ah->flags & AREA_BSS) == 0 )
|
||||
offset += ah->size;
|
||||
qlseek(li, offset);
|
||||
ea_t base = get_area_base(i);
|
||||
validate_array_count(li, &ah->num_relocs, sizeof(reloc_t), "Number of relocs", offset);
|
||||
for ( int j=0; j < ah->num_relocs; j++ )
|
||||
{
|
||||
reloc_t r;
|
||||
lread(li, &r, sizeof(reloc_t));
|
||||
if ( inf_is_be() )
|
||||
{
|
||||
r.type = swap32(r.type);
|
||||
r.offset = swap32(r.offset);
|
||||
}
|
||||
size_t sid = r.sid();
|
||||
ea_t rvalue;
|
||||
ea_t target;
|
||||
fixup_data_t fd;
|
||||
if ( r.type & RF_A )
|
||||
{
|
||||
if ( sid >= ahd->num_syms )
|
||||
loader_failure("Bad relocation record at file offset %" FMT_64 "x", qltell(li)-sizeof(reloc_t));
|
||||
rvalue = delta[sid];
|
||||
target = syms[sid].value + rvalue;
|
||||
fd.set_extdef();
|
||||
}
|
||||
else
|
||||
{
|
||||
rvalue = get_area_base((int)sid);
|
||||
target = rvalue;
|
||||
if ( rvalue == BADADDR )
|
||||
loader_failure("Bad reference to area %" FMT_Z " at file offset %" FMT_64 "x", sid, qltell(li)-sizeof(reloc_t));
|
||||
}
|
||||
segment_t *s = getseg(target);
|
||||
if ( s == NULL )
|
||||
loader_failure("Can't find area for relocation target %a at %" FMT_64 "x", target, qltell(li)-sizeof(reloc_t));
|
||||
fd.sel = s->sel;
|
||||
fd.off = target - get_segm_base(s);
|
||||
if ( (r.type & RF_R) != 0 )
|
||||
{
|
||||
if ( (r.type & RF_A) != 0 )
|
||||
{
|
||||
// R=1 B=0 or R=1 B=1
|
||||
// This specifies PC-relative relocation: to the subject field
|
||||
// is added the difference between the relocation value and
|
||||
// the base of the area containing the subject field.
|
||||
// In pseudo C:
|
||||
// subject_field = subject_field +
|
||||
// (relocation_value -
|
||||
// base_of_area_containing(subject_field))
|
||||
rvalue -= base;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// As a special case, if A is 0, and the relocation value is
|
||||
// specified as the base of the area containing the subject
|
||||
// field, it is not added and:
|
||||
// subject_field = subject_field -
|
||||
// base_of_area_containing(subject_field)
|
||||
// This caters for relocatable PC-relative branches to fixed
|
||||
// target addresses. If R is 1, B is usually 0. A B value of 1
|
||||
// is used to denote that the inter-link-unit value of a
|
||||
// branch destination is to be used, rather than the more
|
||||
// usual intra-link-unit value.
|
||||
rvalue = -base;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (r.type & RF_B) != 0 )
|
||||
{ // R=0 B=1
|
||||
// This specifies based area relocation. The relocation value
|
||||
// must be an address within a based data area. The subject
|
||||
// field is incremented by the difference between this value
|
||||
// and the base address of the consolidated based area group
|
||||
// (the linker consolidates all areas based on the same base
|
||||
// register into a single, contiguous region of the output
|
||||
// image). In pseudo C:
|
||||
// subject_field = subject_field +
|
||||
// (relocation_value -
|
||||
// base_of_area_group_containing(relocation_value))
|
||||
// For example, when generating re-entrant code, the C
|
||||
// compiler places address constants in an adcon area based
|
||||
// on register sb, and loads them using sb relative LDRs.
|
||||
// At link time, separate adcon areas will be merged and sb
|
||||
// will no longer point where presumed at compile time. B
|
||||
// type relocation of the LDR instructions corrects for this.
|
||||
rvalue -= get_area_base((int)sid);
|
||||
}
|
||||
else
|
||||
{ // R=0 B=0
|
||||
// This specifies plain additive relocation: the relocation
|
||||
// value is added to the subject field. In pseudo C:
|
||||
// subject_field = subject_field + relocation_value
|
||||
/* nothing to do */;
|
||||
}
|
||||
}
|
||||
ea_t relea = base + r.offset;
|
||||
switch ( r.type & RF_FT )
|
||||
{
|
||||
case RF_FT_BYTE: // 00 the field to be relocated is a byte
|
||||
fd.set_type(FIXUP_OFF8);
|
||||
fd.displacement = get_byte(relea);
|
||||
add_byte(relea, (uint32)rvalue);
|
||||
break;
|
||||
case RF_FT_HALF: // 01 the field to be relocated is a halfword (two bytes)
|
||||
fd.set_type(FIXUP_OFF16);
|
||||
fd.displacement = get_word(relea);
|
||||
add_word(relea, rvalue);
|
||||
break;
|
||||
case RF_FT_WORD: // 10 the field to be relocated is a word (four bytes)
|
||||
fd.set_type(FIXUP_OFF32);
|
||||
fd.displacement = get_dword(relea);
|
||||
add_dword(relea, rvalue);
|
||||
break;
|
||||
case RF_FT_INSN: // 11 the field to be relocated is an instruction or instruction sequence
|
||||
reloc_insn(relea, (uint32)rvalue, r.type);
|
||||
break;
|
||||
}
|
||||
fd.set(relea);
|
||||
}
|
||||
offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t);
|
||||
}
|
||||
|
||||
if ( ahd->entry_area != 0 )
|
||||
{
|
||||
inf_set_start_cs(ahd->entry_area);
|
||||
inf_set_start_ip(ahd->entry_offset);
|
||||
inf_set_start_ea(ahd->entry_offset);
|
||||
}
|
||||
|
||||
qfree(syms);
|
||||
qfree(delta);
|
||||
qfree(ahd);
|
||||
qfree(strings);
|
||||
qfree(ce);
|
||||
inf_set_baseaddr(0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
246
idasdk76/ldr/aof/aof.h
Normal file
246
idasdk76/ldr/aof/aof.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-97 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
* ARM Object File Loader
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __AOF_H__
|
||||
#define __AOF_H__
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct chunk_header_t
|
||||
{
|
||||
uint32 ChunkFileId;
|
||||
#define AOF_MAGIC 0xC3CBC6C5L // magic value of chunk file
|
||||
#define AOF_MAGIC_B 0xC5C6CBC3L // magic value of chunk file (big endian)
|
||||
uint32 max_chunks; // defines the number of the entries in the
|
||||
// header, fixed when the file is created.
|
||||
uint32 num_chunks; // defines how many chunks are currently used in
|
||||
// the file, which can vary from 0 to maxChunks.
|
||||
// It is redundant in that it can be found by scanning
|
||||
// the entries.
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct chunk_entry_t
|
||||
{
|
||||
char chunkId[8]; // an 8-byte field identifying what data the chunk
|
||||
// contains. Note that this is an 8-byte field, not
|
||||
// a 2-word field, so it has the same byte order
|
||||
// independent of endianness.
|
||||
#define OBJ_HEAD "OBJ_HEAD" // AOF Header
|
||||
#define OBJ_AREA "OBJ_AREA" // Areas
|
||||
#define OBJ_IDFN "OBJ_IDFN" // Identification
|
||||
#define OBJ_SYMT "OBJ_SYMT" // Symbol Table
|
||||
#define OBJ_STRT "OBJ_STRT" // String Table
|
||||
uint32 file_offset; // a one-word field defining the byte offset within
|
||||
// the file of the start of the chunk. All chunks are
|
||||
// word-aligned, so it must be divisible by four.
|
||||
// A value of zero indicates that the chunk entry
|
||||
// is unused.
|
||||
uint32 size; // a one-word field defining the exact byte size
|
||||
// of the chunk's contents (which need not be a
|
||||
// multiple of four).
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct aof_header_t
|
||||
{
|
||||
uint32 obj_file_type; // the value 0xC5E2D080 marks the file as being in
|
||||
// relocatable object format (the usual output of
|
||||
// compilers and assemblers and the usual input to
|
||||
// the linker). The endianness of the object code
|
||||
// can be deduced from this value and must be
|
||||
// identical to the endianness of the containing
|
||||
// chunk file.
|
||||
#define OBJ_FILE_TYPE_MAGIC 0xC5E2D080L
|
||||
uint32 version; // encodes the version of AOF with which the object
|
||||
// file complies
|
||||
// version 1.50 is denoted by decimal 150
|
||||
// version 2.00 is denoted by decimal 200
|
||||
// this version is denoted by decimal 310 (0x136)
|
||||
uint32 num_areas; // Number of Areas
|
||||
uint32 num_syms; // Number of Symbols
|
||||
uint32 entry_area; // Entry Area Index. in the range 1 to Number of
|
||||
// Areas, gives the 1-origin index in the following
|
||||
// array of area headers of the area containing the
|
||||
// entry point. The entry address is defined to be
|
||||
// the base address of this area plus Entry Offset.
|
||||
// A value of 0 for Entry Area Index signifies that
|
||||
// no program entry address is defined by this AOF
|
||||
// file.
|
||||
uint32 entry_offset;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct area_header_t
|
||||
{
|
||||
uint32 name; // Area name (offset into string table)
|
||||
uint32 flags; // Attributes + Alignment
|
||||
// The least significant eight bits of this word
|
||||
// encode the alignment of the start of the area as a
|
||||
// power of 2 and must have a value between 2 and 32.
|
||||
#define AREA_ABS 0x00000100L // The absolute attribute: denotes that the
|
||||
// area must be placed at its Base Address.
|
||||
// This bit is not usually set by language
|
||||
// processors.
|
||||
#define AREA_CODE 0x00000200L // CODE (otherwise DATA)
|
||||
#define AREA_COMMON 0x00000400L // The area is a common definition.
|
||||
#define AREA_COMREF 0x00000800L // The area is a reference to a common block:
|
||||
// preclude the area having initializing data
|
||||
// (see AREA_BSS). In effect, AREA_COMREF
|
||||
// implies AREA_BSS.
|
||||
// If both bits AREA_COMMON and AREA_COMREF
|
||||
// are set, bit AREA_COMREF is ignored.
|
||||
#define AREA_BSS 0x00001000L // Zero-initialized: the area has no
|
||||
// initializing data in this object file,
|
||||
// and that the area contents are missing from
|
||||
// the OBJ_AREA chunk.
|
||||
#define AREA_RDONLY 0x00002000L // Readonly area
|
||||
#define AREA_PIC 0x00004000L // The position independent (PI) area
|
||||
#define AREA_DEBUG 0x00008000L // The debugging table.
|
||||
|
||||
// CODE areas only:
|
||||
|
||||
#define AREA_32BIT 0x00010000L // 32-bit area (not 26bit)
|
||||
#define AREA_REENTR 0x00020000L // The re-entrant area
|
||||
#define AREA_EXTFP 0x00040000L // Extended floating-point instruction set
|
||||
// is used in the area.
|
||||
#define AREA_NOCHK 0x00080000L // No Software Stack Check
|
||||
#define AREA_THUMB 0x00100000L // Thumb code area
|
||||
#define AREA_HALFW 0x00200000L // Halfword instructions may be present
|
||||
#define AREA_INTER 0x00400000L // Area has been compiled to be suitable for
|
||||
// ARM/Thumb interworking.
|
||||
|
||||
// DATA areas only:
|
||||
|
||||
#define AREA_BASED 0x00100000L // Based area
|
||||
inline int get_based_reg() { return int(flags >> 24) & 15; }
|
||||
|
||||
#define AREA_SHARED 0x00200000L // Shared Library Stub Data
|
||||
|
||||
uint32 size; // Area Size. Gives the size of the area in bytes,
|
||||
// which must be a multiple of 4. Unless the
|
||||
// "Not Initialised" bit (bit 12) is set in the area
|
||||
// attributes, there must be this number of bytes
|
||||
// for this area in the OBJ_AREA chunk.
|
||||
// If the "Not Initialised" bit is set, there must be
|
||||
// no initializing bytes for this area in the
|
||||
// OBJ_AREA chunk.
|
||||
uint32 num_relocs; // Number of Relocations. Specifies the number of
|
||||
// relocation directives which apply to this area
|
||||
// (which is equivalent to the number of relocation
|
||||
// records following the area's contents in the
|
||||
// OBJ_AREA chunk.
|
||||
uint32 baseaddr; // Base Address or 0. Is unused unless the area has
|
||||
// the absolute attribute. In this case, the field
|
||||
// records the base address of the area. In general,
|
||||
// giving an area a base address prior to linking
|
||||
// will cause problems for the linker and may prevent
|
||||
// linking altogether, unless only a single object
|
||||
// file is involved.
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// segment flag bits in IDA for ARM module:
|
||||
// the bits are kept in netnode().altval(seg_start_ea)
|
||||
|
||||
#ifdef _NETNODE_HPP
|
||||
#define SEGFL_NETNODE_NAME "$ arm segflags"
|
||||
#define SEGFL_BREG 0x000F
|
||||
#define SEGFL_PIC 0x0010
|
||||
#define SEGFL_REENTR 0x0020
|
||||
#define SEGFL_HALFW 0x0040
|
||||
#define SEGFL_INTER 0x0080
|
||||
#define SEGFL_COMDEF 0x0100
|
||||
#define SEGFL_BASED 0x0200
|
||||
#define SEGFL_ALIGN 0x7C00
|
||||
#define SEGFL_SHIFT 10
|
||||
|
||||
inline void set_arm_segm_flags(ea_t ea, ushort flags)
|
||||
{
|
||||
netnode n;
|
||||
n.create(SEGFL_NETNODE_NAME);
|
||||
n.altset_ea(ea, flags);
|
||||
}
|
||||
|
||||
inline ushort get_arm_segm_flags(ea_t ea)
|
||||
{
|
||||
return (ushort)netnode(SEGFL_NETNODE_NAME).altval_ea(ea);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct reloc_t
|
||||
{
|
||||
uint32 offset;
|
||||
uint32 type; // Low 24bits are SID
|
||||
size_t sid(void) { return size_t(type & 0x00FFFFFFL); }
|
||||
#define RF_II 0x60000000uL // if RF_FT == 11, then:
|
||||
// 00 no constraint (the linker may modify as many contiguous instructions as it needs to)
|
||||
// 01 the linker will modify at most 1 instruction
|
||||
// 10 the linker will modify at most 2 instructions
|
||||
// 11 the linker will modify at most 3 instructions
|
||||
#define RF_B 0x10000000uL // Based
|
||||
#define RF_A 0x08000000uL // 1: The subject field is relocated by the
|
||||
// value of the symbol of which SID is the
|
||||
// zero-origin index in the symbol table
|
||||
// chunk.
|
||||
// 0: The subject field is relocated by the
|
||||
// base of the area of which SID is the
|
||||
// zero-origin index in the array of areas,
|
||||
// (or, equivalently, in the array of area
|
||||
// headers).
|
||||
#define RF_R 0x04000000uL // PC relative
|
||||
#define RF_FT 0x03000000uL
|
||||
#define RF_FT_BYTE 0x00000000uL // 00 the field to be relocated is a byte
|
||||
#define RF_FT_HALF 0x01000000uL // 01 the field to be relocated is a halfword (two bytes)
|
||||
#define RF_FT_WORD 0x02000000uL // 10 the field to be relocated is a word (four bytes)
|
||||
#define RF_FT_INSN 0x03000000uL // 11 the field to be relocated is an instruction or instruction sequence
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct sym_t
|
||||
{
|
||||
uint32 name; // Offset in the string table (in chunk OBJ_STRT) of
|
||||
// the character string name of the symbol.
|
||||
uint32 flags; // Attributes.
|
||||
#define SF_DEF 0x00000001 // Symbol is defined in this file
|
||||
#define SF_PUB 0x00000002 // Symbol has a global scope
|
||||
#define SF_ABS 0x00000004 // Absolute attribute
|
||||
#define SF_ICASE 0x00000008 // Case-insensitive attribute
|
||||
#define SF_WEAK 0x00000010 // Weak attribute
|
||||
#define SF_STRNG 0x00000020 // Strong attribute
|
||||
#define SF_COMM 0x00000040 // Common attribute
|
||||
// Code symbols only:
|
||||
#define SF_CDATA 0x00000100 // Code area datum attribute
|
||||
#define SF_FPREG 0x00000200 // FP args in FP regs attribute
|
||||
#define SF_LEAF 0x00000800 // Simple leaf function attribute
|
||||
#define SF_THUMB 0x00001000 // Thumb symbol
|
||||
uint32 value; // is meaningful only if the symbol is a defining
|
||||
// occurrence (bit 0 of Attributes set), or a common
|
||||
// symbol (bit 6 of Attributes set):
|
||||
// - if the symbol is absolute (bits 0-2 of
|
||||
// Attributes set), this field contains the value
|
||||
// of the symbol
|
||||
// - if the symbol is a common symbol (bit 6 of
|
||||
// Attributes set), this contains the byte length
|
||||
// of the referenced common area
|
||||
// - otherwise, value is interpreted as an offset
|
||||
// from the base address of the area named by
|
||||
// Area Name, which must be an area defined in
|
||||
// this object file
|
||||
uint32 area; // Area Name is meaningful only if the symbol is a
|
||||
// non-absolute defining occurrence (bit 0 of
|
||||
// Attributes set, bit 2 unset). In this case it
|
||||
// gives the index into the string table for the name
|
||||
// of the area in which the symbol is defined (which
|
||||
// must be an area in this object file).
|
||||
};
|
||||
|
||||
#endif
|
||||
20
idasdk76/ldr/aof/makefile
Normal file
20
idasdk76/ldr/aof/makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
PROC=aof
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# the 'unlib' target must be called explicitly
|
||||
.PHONY:
|
||||
unlib: $(F)unlib$(B)
|
||||
$(F)unlib$(B): $(call dumb_target, pro, $(F)unlib$(O))
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)aof$(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 ../idaldr.h aof.cpp aof.h
|
||||
$(F)unlib$(O) : $(I)fpro.h $(I)llong.hpp $(I)pro.h aof.h unlib.cpp
|
||||
199
idasdk76/ldr/aof/unlib.cpp
Normal file
199
idasdk76/ldr/aof/unlib.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-97 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
* ARM Object Librarian (Unpacker)
|
||||
*
|
||||
* This program unpacks a library. It extracts all the modules
|
||||
* from the input library and puts them into separate files.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <pro.h>
|
||||
#include <fpro.h>
|
||||
#include "aof.h"
|
||||
|
||||
#define LIB_DIRY "LIB_DIRY" // Directory
|
||||
#define LIB_TIME "LIB_TIME" // Time stamp
|
||||
#define LIB_VRSN "LIB_VRSN" // Version
|
||||
#define LIB_DATA "LIB_DATA" // Data
|
||||
#define OFL_SYMT "OFL_SYMT" // Symbol table
|
||||
#define OFL_TIME "OFL_TIME" // Time stamp
|
||||
|
||||
static FILE *outfp = NULL;
|
||||
static char outfile[QMAXPATH] = "";
|
||||
static char infile[QMAXPATH] = "";
|
||||
static char modname[MAXSTR] = "";
|
||||
static int mf = 0;
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static void fatal(const char *format,...)
|
||||
{
|
||||
if ( infile[0] != '\0' && modname[0] != '\0' )
|
||||
qeprintf("Fatal [%s] (%s): ",infile,modname);
|
||||
va_list va;
|
||||
va_start(va,format);
|
||||
qveprintf(format,va);
|
||||
va_end(va);
|
||||
qeprintf("\n");
|
||||
qfclose(outfp);
|
||||
unlink(outfile);
|
||||
// qeprintf("press enter to exit.\n");
|
||||
// getchar();
|
||||
qexit(1);
|
||||
}
|
||||
|
||||
void warning(const char *format,...)
|
||||
{
|
||||
qeprintf("Warning [%s] (%s): ",infile,modname);
|
||||
va_list va;
|
||||
va_start(va,format);
|
||||
qveprintf(format,va);
|
||||
va_end(va);
|
||||
qeprintf("\n");
|
||||
}
|
||||
|
||||
static void nomem(const char *format,...)
|
||||
{
|
||||
char buf[512];
|
||||
va_list va;
|
||||
va_start(va,format);
|
||||
qvsnprintf(buf, sizeof(buf), format, va);
|
||||
va_end(va);
|
||||
fatal("No memory: %s",buf);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void *read_chunk(FILE *fp, chunk_entry_t *ce, int32 i)
|
||||
{
|
||||
size_t idx = size_t(i);
|
||||
void *chunk = qalloc_array<char>(ce[idx].size);
|
||||
if ( chunk == NULL )
|
||||
nomem("chunk size %d",size_t(ce[idx].size));
|
||||
qfseek(fp,ce[idx].file_offset,SEEK_SET);
|
||||
if ( qfread(fp,chunk,size_t(ce[idx].size)) != ce[idx].size )
|
||||
fatal("Chunk read error: %s",strerror(errno));
|
||||
return chunk;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static uint32 swap(uint32 x)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32 l;
|
||||
char c[4];
|
||||
} u;
|
||||
char chr;
|
||||
u.l = x;
|
||||
chr = u.c[3]; u.c[3] = u.c[0]; u.c[0] = chr;
|
||||
chr = u.c[2]; u.c[2] = u.c[1]; u.c[1] = chr;
|
||||
return u.l;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void swap_chunk_entry(chunk_entry_t *ce)
|
||||
{
|
||||
ce->file_offset = swap(ce->file_offset);
|
||||
ce->size = swap(ce->size);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
int i;
|
||||
qeprintf("ARM Library unpacker. Copyright 1997 by Ilfak Guilfanov. Version 1.00\n");
|
||||
if ( argc < 2 )
|
||||
fatal("Usage: unlib libfile");
|
||||
qstrncpy(infile, argv[1], sizeof(infile));
|
||||
FILE *fp = qfopen(infile,"rb");
|
||||
if ( fp == NULL )
|
||||
fatal("Can't open library %s",infile);
|
||||
chunk_header_t hd;
|
||||
if ( qfread(fp, &hd, sizeof(hd)) != sizeof(hd)
|
||||
|| (hd.ChunkFileId != AOF_MAGIC && hd.ChunkFileId != AOF_MAGIC_B) )
|
||||
{
|
||||
fatal("Bad library format");
|
||||
}
|
||||
if ( hd.ChunkFileId == AOF_MAGIC_B ) // BIG ENDIAN
|
||||
{
|
||||
mf = 1;
|
||||
hd.max_chunks = swap(hd.max_chunks);
|
||||
hd.num_chunks = swap(hd.num_chunks);
|
||||
}
|
||||
|
||||
chunk_entry_t *ce = qalloc_array<chunk_entry_t>(hd.max_chunks);
|
||||
if ( ce == NULL )
|
||||
nomem("chunk entries (%d)",size_t(hd.max_chunks));
|
||||
qfread(fp, ce, sizeof(chunk_entry_t)*size_t(hd.max_chunks));
|
||||
if ( mf )
|
||||
for ( i=0; i < hd.max_chunks; i++ )
|
||||
swap_chunk_entry(ce+i);
|
||||
|
||||
int vrsn = -1;
|
||||
int diry = -1;
|
||||
int data = 0;
|
||||
for ( i=0; i < hd.max_chunks; i++ )
|
||||
{
|
||||
if ( ce[i].file_offset == 0 )
|
||||
continue;
|
||||
if ( strncmp(ce[i].chunkId,LIB_DIRY,sizeof(ce[i].chunkId)) == 0 )
|
||||
diry = i;
|
||||
if ( strncmp(ce[i].chunkId,LIB_VRSN,sizeof(ce[i].chunkId)) == 0 )
|
||||
vrsn = i;
|
||||
if ( strncmp(ce[i].chunkId,LIB_DATA,sizeof(ce[i].chunkId)) == 0 )
|
||||
data++;
|
||||
}
|
||||
if ( diry == -1 )
|
||||
fatal("Can't find library directory!");
|
||||
if ( data == 0 )
|
||||
fatal("No modules in the library!");
|
||||
if ( vrsn == -1 )
|
||||
fatal("Can't determine library version!");
|
||||
uint32 *version = (uint32 *)read_chunk(fp,ce,vrsn);
|
||||
if ( mf )
|
||||
*version = swap(*version);
|
||||
if ( *version != 1 )
|
||||
fatal("Wrong library version (%ld)",*version);
|
||||
qfree(version);
|
||||
|
||||
uint32 *dir = (uint32 *)read_chunk(fp,ce,diry);
|
||||
uint32 *end = dir + size_t(ce[diry].size/4);
|
||||
while ( dir < end )
|
||||
{
|
||||
uint32 idx = *dir++;
|
||||
/* uint32 elen = */ *dir++;
|
||||
uint32 dlen = *dir++;
|
||||
if ( mf )
|
||||
{
|
||||
idx = swap(idx);
|
||||
dlen = swap(dlen);
|
||||
}
|
||||
if ( idx != 0 )
|
||||
{
|
||||
printf("%d. %s\n",idx,dir);
|
||||
qstrncpy(modname,(char *)dir,sizeof(modname));
|
||||
modname[sizeof(modname)-1] = '\0';
|
||||
void *core = read_chunk(fp,ce,idx);
|
||||
outfp = qfopen(modname,"wb");
|
||||
if ( outfp == NULL )
|
||||
{
|
||||
warning("Can't open output file %s",modname);
|
||||
}
|
||||
else
|
||||
{
|
||||
qfwrite(outfp,core,size_t(ce[size_t(idx)].size));
|
||||
qfclose(outfp);
|
||||
}
|
||||
qfree(core);
|
||||
}
|
||||
dir += size_t(dlen/4);
|
||||
}
|
||||
qfree(dir);
|
||||
|
||||
qfclose(fp);
|
||||
return 0;
|
||||
}
|
||||
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
|
||||
149
idasdk76/ldr/ar/aixar.hpp
Normal file
149
idasdk76/ldr/ar/aixar.hpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/* IBM_PROLOG_BEGIN_TAG */
|
||||
/* This is an automatically generated prolog. */
|
||||
/* */
|
||||
/* bos420 src/bos/usr/include/ar.h */
|
||||
/* */
|
||||
/* Licensed Materials - Property of IBM */
|
||||
/* */
|
||||
/* (C) COPYRIGHT International Business Machines Corp. 1989,1995 */
|
||||
/* All Rights Reserved */
|
||||
/* */
|
||||
/* US Government Users Restricted Rights - Use, duplication or */
|
||||
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */
|
||||
/* */
|
||||
/* IBM_PROLOG_END_TAG */
|
||||
/* @(#)25 1.8 src/bos/usr/include/ar.h, cmdar, bos420, 9613T 6/16/90 00:07:48 */
|
||||
/* ar.h 5.1 - 86/12/09 - 06:03:39 */
|
||||
#ifndef _H_AR
|
||||
#define _H_AR
|
||||
#pragma pack(push, 1)
|
||||
/*
|
||||
* COMPONENT_NAME: CMDAR
|
||||
*
|
||||
* FUNCTIONS: none
|
||||
*
|
||||
* ORIGINS: 27, 3
|
||||
*
|
||||
* (C) COPYRIGHT International Business Machines Corp. 1989
|
||||
* All Rights Reserved
|
||||
* Licensed Materials - Property of IBM
|
||||
*
|
||||
* US Government Users Restricted Rights - Use, duplication or
|
||||
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
||||
*/
|
||||
|
||||
/* AIX INDEXED ARCHIVE FORMAT
|
||||
*
|
||||
* ARCHIVE File Organization:
|
||||
* _____________________________________________
|
||||
* |__________FIXED HEADER "fl_hdr"______________|
|
||||
* +--- | |
|
||||
* | |__________ARCHIVE_FILE_MEMBER_1______________|
|
||||
* +--> | |
|
||||
* | Archive Member Header "ar_hdr" |
|
||||
* +--- |.............................................| <--+
|
||||
* | | Member Contents | |
|
||||
* | |_____________________________________________| |
|
||||
* | |________ARCHIVE_FILE_MEMBER_2________________| |
|
||||
* +--> | | ---+
|
||||
* | Archive Member Header "ar_hdr" |
|
||||
* +--- |.............................................| <--+
|
||||
* | | Member Contents | |
|
||||
* | |_____________________________________________| |
|
||||
* | | . . . | |
|
||||
* . | . . . | .
|
||||
* . | . . . | .
|
||||
* . |_____________________________________________| .
|
||||
* | |________ARCHIVE_FILE_MEMBER_n-1______________| |
|
||||
* +--> | | ---+
|
||||
* | Archive Member Header "ar_hdr" |
|
||||
* +--- |.............................................| <--+
|
||||
* | | Member Contents | |
|
||||
* | | (Member Table, always present) | |
|
||||
* | |_____________________________________________| |
|
||||
* | |_____________________________________________| |
|
||||
* | |________ARCHIVE_FILE_MEMBER_n________________| |
|
||||
* | | | |
|
||||
* +--> | Archive Member Header "ar_hdr" | ---+
|
||||
* |.............................................|
|
||||
* | Member Contents |
|
||||
* | (Global Symbol Table if present) |
|
||||
* |_____________________________________________|
|
||||
*
|
||||
*/
|
||||
|
||||
#define AIAMAG "<aiaff>\n"
|
||||
#define AIAMAGBIG "<bigaf>\n"
|
||||
#define SAIAMAG 8
|
||||
#define AIAFMAG "`\n"
|
||||
|
||||
struct fl_hdr /* archive fixed length header */
|
||||
{
|
||||
char fl_magic[SAIAMAG]; /* Archive magic string */
|
||||
char fl_memoff[20]; /*Offset to member table */
|
||||
char fl_gstoff[20]; /*Offset to global symbol table */
|
||||
char fl_gst64off[20]; /*Offset global symbol table for 64-bit objects */
|
||||
char fl_fstmoff[20]; /*Offset to first archive member */
|
||||
char fl_lstmoff[20]; /*Offset to last archive member */
|
||||
char fl_freeoff[20]; /*Offset to first mem on free list */
|
||||
};
|
||||
|
||||
struct aix_ar_hdr /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_size[20]; /* File member size - decimal */
|
||||
char ar_nxtmem[20]; /* Next member offset-decimal */
|
||||
char ar_prvmem[20]; /* Previous member offset-dec */
|
||||
char ar_date[12]; /* File member date-decimal */
|
||||
char ar_uid[12]; /* File member userid-decimal */
|
||||
char ar_gid[12]; /* File member group id-decimal */
|
||||
char ar_mode[12]; /* File member mode-octal */
|
||||
char ar_namlen[4]; /* File member name length-dec */
|
||||
#if 0
|
||||
union
|
||||
{
|
||||
char ar_name[2]; /* variable length member name */
|
||||
char ar_fmag[2]; /* AIAFMAG - string to end header */
|
||||
} _ar_name; /* and variable length name */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fl_hdr_small /* archive fixed length header (prior to Version 4.3) */
|
||||
{
|
||||
char fl_magic[SAIAMAG]; /* Archive file magic string */
|
||||
char fl_memoff[12]; /* Offset to member table */
|
||||
char fl_gstoff[12]; /* Offset to global symbol table */
|
||||
char fl_fstmoff[12]; /* Offset to first archive member */
|
||||
char fl_lstmoff[12]; /* Offset to last archive member */
|
||||
char fl_freeoff[12]; /* Offset to first mem on free list */
|
||||
};
|
||||
|
||||
struct aix_ar_hdr_small /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_size[12]; /* file member size - decimal */
|
||||
char ar_nxtmem[12]; /* pointer to next member - decimal */
|
||||
char ar_prvmem[12]; /* pointer to previous member - decimal */
|
||||
char ar_date[12]; /* file member date - decimal */
|
||||
char ar_uid[12]; /* file member user id - decimal */
|
||||
char ar_gid[12]; /* file member group id - decimal */
|
||||
char ar_mode[12]; /* file member mode - octal */
|
||||
char ar_namlen[4]; /* file member name length - decimal */
|
||||
#if 0
|
||||
union
|
||||
{
|
||||
char ar_name[2]; /* variable length member name */
|
||||
char ar_fmag[2]; /* AIAFMAG - string to end header */
|
||||
} _ar_name; /* and variable length name */
|
||||
#endif
|
||||
};
|
||||
/*
|
||||
* Note: 'ar_namlen' contains the length of the member name which
|
||||
* may be up to 255 chars. The character string containing
|
||||
* the name begins at '_ar_name.ar_name'. The terminating
|
||||
* string AIAFMAG, is only cosmetic. File member contents begin
|
||||
* at the first even byte boundary past 'header position +
|
||||
* sizeof(struct ar_hdr) + ar_namlen', and continue for
|
||||
* 'ar_size' bytes.
|
||||
*/
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* _H_AR */
|
||||
113
idasdk76/ldr/ar/ar.hpp
Normal file
113
idasdk76/ldr/ar/ar.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/* So far this is correct for BSDish archives. Don't forget that
|
||||
files must begin on an even byte boundary. */
|
||||
|
||||
#ifndef __AR_H__
|
||||
#define __AR_H__
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* Note that the usual '\n' in magic strings may translate to different
|
||||
characters, as allowed by ANSI. '\012' has a fixed value, and remains
|
||||
compatible with existing BSDish archives. */
|
||||
|
||||
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
|
||||
#define ARMAGB "!<bout>\012" /* For b.out archives */
|
||||
#define ARMAGE "!<elf_>\012" /* For ELF archives */
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\012"
|
||||
|
||||
/* The ar_date field of the armap (__.SYMDEF) member of an archive
|
||||
must be greater than the modified date of the entire file, or
|
||||
BSD-derived linkers complain. We originally write the ar_date with
|
||||
this offset from the real file's mod-time. After finishing the
|
||||
file, we rewrite ar_date if it's not still greater than the mod date. */
|
||||
|
||||
#define ARMAP_TIME_OFFSET 60
|
||||
|
||||
struct ar_hdr
|
||||
{
|
||||
char ar_name[16]; /* name of this member */
|
||||
char ar_date[12]; /* file mtime */
|
||||
char ar_uid[6]; /* owner uid; printed as decimal */
|
||||
char ar_gid[6]; /* owner gid; printed as decimal */
|
||||
char ar_mode[8]; /* file mode, printed as octal */
|
||||
char ar_size[10]; /* file size, printed as decimal */
|
||||
char ar_fmag[2]; /* should contain ARFMAG */
|
||||
};
|
||||
|
||||
#define AR_EFMT1 "#1/" /* extended format #1: BSD/Apple archives */
|
||||
|
||||
// ig. get all module names from ar
|
||||
|
||||
int process_ar(
|
||||
char *libfile, /* return 0 - ok */
|
||||
int (*_callback)(
|
||||
void *ud,
|
||||
int32 offset,
|
||||
int method,
|
||||
uint32 csize,
|
||||
uint32 ucsize,
|
||||
uint32 attributes,
|
||||
const char *filename),
|
||||
void *ud);
|
||||
|
||||
// The first linker member has the following format. This information appears after the
|
||||
// header:
|
||||
//
|
||||
// Offset Size Field Description
|
||||
// 0 4 Number of Symbols Unsigned long containing the number of symbols indexed.
|
||||
// This number is stored in big-endian format. Each object-file member
|
||||
// typically defines one or more external symbols.
|
||||
// 4 4*n Offsets Array of file offsets to archive member headers, in which n is
|
||||
// equal to Number of Symbols. Each number in the array is an unsigned long
|
||||
// stored in big-endian format. For each symbol named in the String Table,
|
||||
// the corresponding element in the Offsets array gives the location of the
|
||||
// archive member that contains the symbol.
|
||||
// * * String Table Series of null-terminated strings that name all the symbols
|
||||
// in the directory. Each string begins immediately after the null character
|
||||
// in the previous string. The number of strings must be equal to the value
|
||||
// of the Number of Symbols fields.
|
||||
//
|
||||
// -----------------------------
|
||||
// The second linker member has the name '\' as does the first linker member. Although
|
||||
// both the linker members provide a directory of symbols and archive members that contain
|
||||
// them, the second linker member is used in preference to the first by all current
|
||||
// linkers. The second linker member includes symbol names in lexical order, which enables
|
||||
// faster searching by name.
|
||||
//
|
||||
// The first second member has the following format. This information appears after the
|
||||
// header:
|
||||
//
|
||||
// Offset Size Field Description
|
||||
// 0 4 Number of Members Unsigned long containing the number of archive members.
|
||||
// 4 4*m Offsets Array of file offsets to archive member headers, arranged in
|
||||
// ascending order. Each offset is an unsigned long. The number m is equal
|
||||
// to the value of the Number of Members field.
|
||||
// * 4 Number of Symbols Unsigned long containing the number of symbols indexed.
|
||||
// Each object-file member typically defines one or more external symbols.
|
||||
// * 2*n Indices Array of 1-based indices (unsigned short) which map symbol names
|
||||
// to archive member offsets. The number n is equal to Number of Symbols.
|
||||
// For each symbol named in the String Table, the corresponding element in
|
||||
// the Indices array gives an index into the Offsets array. The Offsets
|
||||
// array, in turn, gives the location of the archive member that contains
|
||||
// the symbol.
|
||||
// * * String Table Series of null-terminated strings that name all the symbols
|
||||
// in the directory. Each string begins immediately after the null byte in
|
||||
// the previous string. The number of strings must be equal to the value of
|
||||
// the Number of Symbols fields. This table lists all the symbol names in
|
||||
// ascending lexical order.
|
||||
//
|
||||
// //-----------------------------
|
||||
// The name of the longnames member is '\\'. The longnames member is a series of
|
||||
// strings of archive member names. A name appears here only when there is insufficient
|
||||
// room in the Name field (16 bytes). The longnames member can be empty, though its
|
||||
// header must appear.
|
||||
//
|
||||
// The strings are null-terminated. Each string begins immediately after the null byte
|
||||
// in the previous string.
|
||||
//
|
||||
|
||||
bool is_ar_file(linput_t *li, qoff64_t offset, bool include_aix);
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* __AR_H__ */
|
||||
|
||||
238
idasdk76/ldr/ar/arcmn.cpp
Normal file
238
idasdk76/ldr/ar/arcmn.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
|
||||
#include <diskio.hpp>
|
||||
|
||||
#define MAGICLEN ((SARMAG > SAIAMAG) ? SARMAG : SAIAMAG)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool is_ar_file(linput_t *li, qoff64_t offset, bool include_aix)
|
||||
{
|
||||
char magic[MAGICLEN];
|
||||
qlseek(li, offset);
|
||||
if ( qlread(li, magic, sizeof(magic)) != sizeof(magic) )
|
||||
return false;
|
||||
return memcmp(magic, ARMAG, SARMAG) == 0
|
||||
|| memcmp(magic, ARMAGB, SARMAG) == 0
|
||||
|| memcmp(magic, ARMAGE, SARMAG) == 0
|
||||
|| include_aix
|
||||
&& (memcmp(magic,AIAMAG,SAIAMAG) == 0
|
||||
|| memcmp(magic,AIAMAGBIG,SAIAMAG) == 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static char *get_msft_module_name(
|
||||
const char *ahname,
|
||||
const char *ahend,
|
||||
char *name,
|
||||
size_t size)
|
||||
{
|
||||
if ( size == 0 )
|
||||
return NULL;
|
||||
char *ptr = name;
|
||||
for ( size_t i=0; ahname < ahend; i++,ptr++ )
|
||||
{
|
||||
char chr = *ahname++;
|
||||
if ( chr == '\n' || i == size-1 )
|
||||
chr = '\0';
|
||||
*ptr = chr;
|
||||
if ( chr == '\0' )
|
||||
break;
|
||||
}
|
||||
while ( ptr > name && qisspace(ptr[-1]) )
|
||||
*--ptr = '\0';
|
||||
if ( ptr > name && ptr[-1] == '/' )
|
||||
ptr[-1] = '\0';
|
||||
return name;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static const char *get_ar_modname(
|
||||
const char *lnames,
|
||||
const char *end,
|
||||
const char *name,
|
||||
char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
if ( lnames != NULL && *name == '/' )
|
||||
{
|
||||
name++;
|
||||
size_t off = size_t(atol(name));
|
||||
while ( qisdigit(*name) )
|
||||
name++;
|
||||
if ( *name == '\0' )
|
||||
{
|
||||
if ( lnames+off < lnames )
|
||||
return qstrncpy(buf, "?", bufsize);
|
||||
return get_msft_module_name(lnames+off, end, buf, bufsize);
|
||||
}
|
||||
}
|
||||
return qstrncpy(buf, name, bufsize);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// return codes:
|
||||
// 0: ok
|
||||
// 1: no input file
|
||||
// 2: read error
|
||||
// 3: bad archive
|
||||
// 4: not enough memory
|
||||
// 5: maxpos reached
|
||||
|
||||
struct ar_visitor_t
|
||||
{
|
||||
virtual ssize_t idaapi visit_ar_module(
|
||||
qoff64_t offset,
|
||||
ar_hdr *ah,
|
||||
uint64 size,
|
||||
char *filename) = 0;
|
||||
};
|
||||
|
||||
// Enumerate modules in AR archive.
|
||||
// \param maxpos Max position in file. Typically is used when
|
||||
// archive is embedded within other file.
|
||||
ssize_t enum_ar_contents(linput_t *li, ar_visitor_t &av, int32 maxpos = -1)
|
||||
{
|
||||
ssize_t code = 0;
|
||||
char *names = NULL;
|
||||
size_t names_size = 0;
|
||||
while ( true )
|
||||
{
|
||||
ar_hdr ah;
|
||||
qoff64_t filepos = qltell(li);
|
||||
if ( filepos & 1 )
|
||||
qlseek(li, filepos+1);
|
||||
if ( maxpos > -1 && filepos >= maxpos )
|
||||
{
|
||||
code = 5;
|
||||
break;
|
||||
}
|
||||
ssize_t bytes = qlread(li, &ah, sizeof(ah));
|
||||
if ( bytes == 0 )
|
||||
break; // end of archive, no error
|
||||
if ( bytes != sizeof(ah) )
|
||||
{
|
||||
code = 2; // read error
|
||||
break;
|
||||
}
|
||||
if ( memcmp(ah.ar_fmag, ARFMAG, sizeof(ah.ar_fmag)) != 0 )
|
||||
{
|
||||
code = 3; // bad archive
|
||||
break;
|
||||
}
|
||||
char name[sizeof(ah.ar_name)+1];
|
||||
get_msft_module_name(ah.ar_name, ah.ar_name+sizeof(ah.ar_name), name, sizeof(name));
|
||||
uint64 size = qatoll(ah.ar_size);
|
||||
filepos = qltell(li);
|
||||
if ( names == NULL && name[0] == '/' && name[1] == '\0' )
|
||||
{
|
||||
if ( size != 0 )
|
||||
{
|
||||
names = (char *)qalloc(size);
|
||||
if ( names == NULL )
|
||||
{
|
||||
code = 4; // not enough memory
|
||||
break;
|
||||
}
|
||||
names_size = size;
|
||||
if ( qlread(li, names, size) != size )
|
||||
{
|
||||
code = 2; // read error
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( memcmp(name, AR_EFMT1, 3) == 0 )
|
||||
{
|
||||
// BSD/Apple archive: the length of long name follows
|
||||
// #1/nnn
|
||||
size_t extralen = size_t(atol(name+3));
|
||||
char *modname = (char *)qalloc(extralen+1);
|
||||
if ( modname == NULL )
|
||||
{
|
||||
code = 4; // not enough memory
|
||||
break;
|
||||
}
|
||||
if ( qlread(li, modname, extralen) != extralen )
|
||||
{
|
||||
code = 2; // read error
|
||||
break;
|
||||
}
|
||||
modname[extralen]='\0';
|
||||
|
||||
// skip special files
|
||||
if ( !strneq(modname, "__.SYMDEF", sizeof("__.SYMDEF")-1) )
|
||||
{
|
||||
code = av.visit_ar_module(qoff64_t(filepos+extralen), &ah, size-extralen, modname);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
qfree(modname);
|
||||
}
|
||||
else if ( name[0] != '\0' )
|
||||
{
|
||||
char modname[MAXSTR];
|
||||
get_ar_modname(names, names+names_size, name, modname, sizeof(modname));
|
||||
code = av.visit_ar_module(filepos, &ah, size, modname);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
qlseek(li, qoff64_t(filepos+size));
|
||||
}
|
||||
qfree(names);
|
||||
return code;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// convert small archive header to big one
|
||||
bool upgrade_aix_fl_hdr(fl_hdr *fh, const fl_hdr_small *fh_small)
|
||||
{
|
||||
if ( memcmp(fh_small->fl_magic, AIAMAG, SAIAMAG) != 0 )
|
||||
return false; // not small archive
|
||||
qstrncpy(fh->fl_memoff, fh_small->fl_memoff, sizeof(fh->fl_memoff));
|
||||
qstrncpy(fh->fl_gstoff, fh_small->fl_gstoff, sizeof(fh->fl_gstoff));
|
||||
fh->fl_gst64off[0] = '\0';
|
||||
qstrncpy(fh->fl_fstmoff, fh_small->fl_fstmoff, sizeof(fh->fl_fstmoff));
|
||||
qstrncpy(fh->fl_lstmoff, fh_small->fl_lstmoff, sizeof(fh->fl_lstmoff));
|
||||
qstrncpy(fh->fl_freeoff, fh_small->fl_freeoff, sizeof(fh->fl_freeoff));
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool read_aix_fl_hdr(fl_hdr *fh, linput_t *li)
|
||||
{
|
||||
size_t nread = qlread(li, fh, sizeof(*fh));
|
||||
if ( nread == sizeof(*fh) && memcmp(fh->fl_magic, AIAMAGBIG, SAIAMAG) == 0 )
|
||||
return true;
|
||||
if ( nread < sizeof(fl_hdr_small) )
|
||||
return false;
|
||||
fl_hdr_small fh_small;
|
||||
memcpy(&fh_small, fh, sizeof(fh_small)); //-V512 call of the 'memcpy' function will lead to underflow of the buffer
|
||||
return upgrade_aix_fl_hdr(fh, &fh_small);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// convert small member header to big one
|
||||
void upgrade_aix_ar_hdr(aix_ar_hdr *ah, const aix_ar_hdr_small *ah_small)
|
||||
{
|
||||
qstrncpy(ah->ar_size, ah_small->ar_size, sizeof(ah->ar_size));
|
||||
qstrncpy(ah->ar_nxtmem, ah_small->ar_nxtmem, sizeof(ah->ar_nxtmem));
|
||||
qstrncpy(ah->ar_prvmem, ah_small->ar_prvmem, sizeof(ah->ar_prvmem));
|
||||
qstrncpy(ah->ar_date, ah_small->ar_date, sizeof(ah->ar_date));
|
||||
qstrncpy(ah->ar_uid, ah_small->ar_uid, sizeof(ah->ar_uid));
|
||||
qstrncpy(ah->ar_gid, ah_small->ar_gid, sizeof(ah->ar_gid));
|
||||
qstrncpy(ah->ar_mode, ah_small->ar_mode, sizeof(ah->ar_mode));
|
||||
qstrncpy(ah->ar_namlen, ah_small->ar_namlen, sizeof(ah->ar_namlen));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool read_aix_ar_hdr(aix_ar_hdr *ah, const fl_hdr *fh, linput_t *li)
|
||||
{
|
||||
if ( memcmp(fh->fl_magic, AIAMAGBIG, SAIAMAG) == 0 )
|
||||
return qlread(li, ah, sizeof(*ah)) == sizeof(*ah);
|
||||
aix_ar_hdr_small ah_small;
|
||||
if ( qlread(li, &ah_small, sizeof(ah_small)) != sizeof(ah_small) )
|
||||
return false;
|
||||
upgrade_aix_ar_hdr(ah, &ah_small);
|
||||
return true;
|
||||
}
|
||||
|
||||
91
idasdk76/ldr/coff/dbxstcla.h
Normal file
91
idasdk76/ldr/coff/dbxstcla.h
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef _H_DBXSTCLASS
|
||||
#define _H_DBXSTCLASS
|
||||
/*
|
||||
* XCOFF STORAGE CLASSES AND STABSTRINGS DESIGNED SPECIFICALLY FOR DBX
|
||||
*/
|
||||
#define DBXMASK 0x80
|
||||
|
||||
#define C_GSYM 0x80 // Global variable.
|
||||
#define C_LSYM 0x81 // Automatic variable allocated on stack.
|
||||
#define C_PSYM 0x82 // Argument to subroutine allocated on stack.
|
||||
#define C_RSYM 0x83 // Register variable.
|
||||
#define C_RPSYM 0x84 // Argument to function or procedure stored in the register.
|
||||
#define C_STSYM 0x85 // Statically allocated symbol.
|
||||
#define C_TCSYM 0x86
|
||||
#define C_BCOMM 0x87 // Beginning of common block.
|
||||
#define C_ECOML 0x88 // Local member of common block.
|
||||
#define C_ECOMM 0x89 // End of common block.
|
||||
#define C_DECL 0x8c // Declaration of object.
|
||||
#define C_ENTRY 0x8d // Alternate entry.
|
||||
#define C_FUN 0x8e // Function or procedure.
|
||||
#define C_BSTAT 0x8f // Beginning of static block.
|
||||
#define C_ESTAT 0x90 // End of static block.
|
||||
|
||||
#define TP_ARRAY \
|
||||
{\
|
||||
"int:t-1=r-1;-2147483648;2147483647",\
|
||||
"char:t-2=@s8;r-2;0;255",\
|
||||
"short:t-3=@s16;r-3;-32768;32767",\
|
||||
"long:t-4=-1",\
|
||||
"unsigned char:t-5=@s8;r-5;0;255",\
|
||||
"signed char:t-6=@s8;r-6;-128;127",\
|
||||
"unsigned short:t-7=@s16;r-7;0;65535",\
|
||||
"unsigned int:t-8=r-8;0;4294967295",\
|
||||
"unsigned:t-9=-8",\
|
||||
"unsigned long:t-10=-8",\
|
||||
"void:t-11=r-11;0;0",\
|
||||
"float:t-12=g-12;4",\
|
||||
"double:t-13=g-12;8",\
|
||||
"long double:t-14=g-12;10",\
|
||||
"integer:t-15=-1",\
|
||||
"boolean:t-16=efalse:0,true:1,",\
|
||||
"shortreal:t-17=g-12;4",\
|
||||
"real:t-18=g-12;8",\
|
||||
"stringptr:t-19=N-19",\
|
||||
"character:t-20=@s8;r-20;0;255",\
|
||||
"logical*1:t-21=@s8;r-21;0;255",\
|
||||
"logical*2:t-22=@s16;r-22;0;65535",\
|
||||
"logical*4:t-23=r-23;0;4294967295",\
|
||||
"logical:t-24=-23",\
|
||||
"complex:t-25=c-25;8",\
|
||||
"double complex:t-26=c-25;16",\
|
||||
"integer*1:t-27=-6",\
|
||||
"integer*2:t-28=-3",\
|
||||
"integer*4:t-29=-1",\
|
||||
"wchar:t-30=@s16;r-30;0;65535" \
|
||||
}
|
||||
|
||||
#define TP_INT (-1)
|
||||
#define TP_CHAR (-2)
|
||||
#define TP_SHORT (-3)
|
||||
#define TP_LONG (-4)
|
||||
#define TP_UCHAR (-5)
|
||||
#define TP_SCHAR (-6)
|
||||
#define TP_USHORT (-7)
|
||||
#define TP_UINT (-8)
|
||||
#define TP_UNSIGNED (-9)
|
||||
#define TP_ULONG (-10)
|
||||
#define TP_VOID (-11)
|
||||
#define TP_FLOAT (-12)
|
||||
#define TP_DOUBLE (-13)
|
||||
#define TP_LDOUBLE (-14)
|
||||
#define TP_PASINT (-15)
|
||||
#define TP_BOOL (-16)
|
||||
#define TP_SHRTREAL (-17)
|
||||
#define TP_REAL (-18)
|
||||
#define TP_STRNGPTR (-19)
|
||||
#define TP_FCHAR (-20)
|
||||
#define TP_LOGICAL1 (-21)
|
||||
#define TP_LOGICAL2 (-22)
|
||||
#define TP_LOGICAL4 (-23)
|
||||
#define TP_LOGICAL (-24)
|
||||
#define TP_COMPLEX (-25)
|
||||
#define TP_DCOMPLEX (-26)
|
||||
#define TP_INTEGER1 (-27)
|
||||
#define TP_INTEGER2 (-28)
|
||||
#define TP_INTEGER4 (-29)
|
||||
#define TP_WCHAR (-30)
|
||||
|
||||
#define TP_NTYPES 30
|
||||
|
||||
#endif /* _H_DBXSTCLASS */
|
||||
82
idasdk76/ldr/coff/storclas.h
Normal file
82
idasdk76/ldr/coff/storclas.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef _H_STCLASS
|
||||
#define _H_STCLASS
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* COFF Extended Object File Format:
|
||||
* storclass.h
|
||||
* Derived from AT&T UNIX System V Release 2.0 COFF
|
||||
*
|
||||
* Structure similar to original COFF
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/*
|
||||
* STORAGE CLASSES
|
||||
*/
|
||||
|
||||
/* This used to be defined as -1, but now n_sclass is unsigned. */
|
||||
#define C_EFCN 0xff /* physical end of function */
|
||||
#define C_NULL 0
|
||||
#define C_AUTO 1 /* automatic variable */
|
||||
#define C_EXT 2 /* external symbol */
|
||||
#define C_STAT 3 /* static */
|
||||
#define C_REG 4 /* register variable */
|
||||
#define C_EXTDEF 5 /* external definition */
|
||||
#define C_LABEL 6 /* label */
|
||||
#define C_ULABEL 7 /* undefined label */
|
||||
#define C_MOS 8 /* member of structure */
|
||||
#define C_ARG 9 /* function argument */
|
||||
#define C_STRTAG 10 /* structure tag */
|
||||
#define C_MOU 11 /* member of union */
|
||||
#define C_UNTAG 12 /* union tag */
|
||||
#define C_TPDEF 13 /* type definition */
|
||||
#define C_USTATIC 14 /* undefined static */
|
||||
#define C_ENTAG 15 /* enumeration tag */
|
||||
#define C_MOE 16 /* member of enumeration */
|
||||
#define C_REGPARM 17 /* register parameter */
|
||||
#define C_FIELD 18 /* bit field */
|
||||
#define C_AUTOARG 19 /* auto argument */
|
||||
#define C_LASTENT 20 /* dummy entry (end of block) */
|
||||
#define C_BLOCK 100 /* ".bb" or ".eb" */
|
||||
#define C_FCN 101 /* ".bf" or ".ef" */
|
||||
#define C_EOS 102 /* end of structure */
|
||||
#define C_FILE 103 /* file name */
|
||||
#define C_LINE 104 /* line # reformatted as symbol table entry */
|
||||
#define C_ALIAS 105 /* duplicate tag */
|
||||
#define C_HIDDEN 106 /* ext symbol in dmert public lib */
|
||||
|
||||
/* New storage classes for WINDOWS_NT */
|
||||
#define C_SECTION 104 /* section name */
|
||||
#define C_NT_WEAK 105 /* weak external */
|
||||
|
||||
/* New storage classes for 80960 */
|
||||
|
||||
/* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */
|
||||
#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
|
||||
|
||||
#define C_SCALL 107 /* Procedure reachable via system call */
|
||||
#define C_LEAFEXT 108 /* External leaf */
|
||||
#define C_LEAFSTAT 113 /* Static leaf */
|
||||
#define C_OPTVAR 109 /* Optimized variable */
|
||||
#define C_DEFINE 110 /* Preprocessor #define */
|
||||
#define C_PRAGMA 111 /* Advice to compiler or linker */
|
||||
#define C_SEGMENT 112 /* 80960 segment name */
|
||||
|
||||
/* Storage classes for m88k */
|
||||
#define C_SHADOW 107 /* shadow symbol */
|
||||
#define C_VERSION 108 /* coff version symbol */
|
||||
|
||||
/* New storage classes for RS/6000 */
|
||||
#define C_HIDEXT 107 /* Un-named external symbol */
|
||||
#define C_BINCL 108 /* Marks beginning of include file */
|
||||
#define C_EINCL 109 /* Marks ending of include file */
|
||||
#define C_WEAKEXT 111 /* Weak external symbol */
|
||||
|
||||
/* Storage classes for MS Windows */
|
||||
|
||||
#define IMAGE_SYM_CLASS_TOKEN 107
|
||||
|
||||
#include <../ldr/coff/dbxstcla.h>
|
||||
|
||||
#endif /* _H_STCLASS */
|
||||
862
idasdk76/ldr/coff/syms.h
Normal file
862
idasdk76/ldr/coff/syms.h
Normal file
@@ -0,0 +1,862 @@
|
||||
#ifndef _H_SYMS
|
||||
#define _H_SYMS
|
||||
|
||||
#include <../ldr/coff/storclas.h>
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define SYMNMLEN 8 /* Number of characters in a symbol name */
|
||||
#define FILNMLEN 14 /* Number of characters in a file name */
|
||||
#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */
|
||||
|
||||
struct coff_sym_t // here for efd(di) and ldr/dbg
|
||||
{
|
||||
union
|
||||
{
|
||||
char _n_name[SYMNMLEN]; /* old COFF version */
|
||||
struct
|
||||
{
|
||||
int32 _n_zeroes; /* new == 0 */
|
||||
int32 _n_offset; /* offset into string table */
|
||||
} _n_n;
|
||||
// char *_n_nptr[2]; /* allows for overlaying */
|
||||
} _n;
|
||||
uint32 n_value; /* value of symbol */
|
||||
uint16 n_scnum; /* section number */
|
||||
uint16 n_type; /* type and derived type */
|
||||
uchar n_sclass; /* storage class */
|
||||
uchar n_numaux; /* number of aux. entries */
|
||||
};
|
||||
|
||||
struct coff_sym64_t
|
||||
{
|
||||
uint64 n_value64; /* value of symbol */
|
||||
uint32 n_offset64; /* offset into string table */
|
||||
uint16 n_scnum; /* section number */
|
||||
union
|
||||
{
|
||||
unsigned short _n_type; /* type and derived type */
|
||||
struct
|
||||
{
|
||||
unsigned char _n_lang; /* source language id */
|
||||
unsigned char _n_cpu; /* cputype id */
|
||||
} _n_lc;
|
||||
} _n_tylc;
|
||||
char n_sclass; /* storage class */
|
||||
char n_numaux; /* number of aux. entries */
|
||||
};
|
||||
|
||||
#define IDA_SYM_SZ (SYMNMLEN + 8 + 4 + 2 + 2*1)
|
||||
|
||||
struct ida_sym_t // internal, translated form
|
||||
{
|
||||
union
|
||||
{
|
||||
char _n_name[SYMNMLEN]; /* old for short name (<=8) */
|
||||
struct
|
||||
{
|
||||
int32 _n_zeroes; /* for long name == 0 */
|
||||
int32 _n_offset; /* offset into string table */
|
||||
} _n_n;
|
||||
} _n;
|
||||
uint64 n_value; /* value of symbol */
|
||||
uint32 n_scnum; /* section number */
|
||||
uint16 n_type; /* type and derived type */
|
||||
uchar n_sclass; /* storage class */
|
||||
uchar n_numaux; /* number of aux. entries */
|
||||
};
|
||||
|
||||
DECLARE_TYPE_AS_MOVABLE(ida_sym_t);
|
||||
|
||||
#define COFF_SYM_SZ (SYMNMLEN + 4 + 2*2 + 2*1)
|
||||
#define COFF_SYM64_SZ (8 + 4 + 2 + 2 + 2*1)
|
||||
#define n_name _n._n_name
|
||||
#define n_nptr _n._n_nptr[1]
|
||||
#define n_zeroes _n._n_n._n_zeroes
|
||||
#define n_offset _n._n_n._n_offset
|
||||
|
||||
/*
|
||||
* Relocatable symbols have a section number of the
|
||||
* section in which they are defined. Otherwise, section
|
||||
* numbers have the following meanings:
|
||||
*/
|
||||
#define N_UNDEF 0 // undefined symbol
|
||||
#define N_ABS uint16(-1) // value of symbol is absolute
|
||||
#define N_DEBUG uint16(-2) // special debugging symbol -- value of symbol is meaningless
|
||||
#define N_TV uint16(-3) // indicates symbol needs transfer vector (preload)
|
||||
#define P_TV uint16(-4) // indicates symbol needs transfer vector (postload)
|
||||
|
||||
/*
|
||||
* The fundamental type of a symbol packed into the low
|
||||
* 4 bits of the word.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define _EF ".ef"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Type of a symbol, in low N bits of the word
|
||||
*/
|
||||
#define T_NULL 0
|
||||
#define T_VOID 1 /* function argument (only used by compiler) */
|
||||
#define T_CHAR 2 /* character */
|
||||
#define T_SHORT 3 /* short integer */
|
||||
#define T_INT 4 /* integer */
|
||||
#define T_LONG 5 /* long integer */
|
||||
#define T_FLOAT 6 /* floating point */
|
||||
#define T_DOUBLE 7 /* double word */
|
||||
#define T_STRUCT 8 /* structure */
|
||||
#define T_UNION 9 /* union */
|
||||
#define T_ENUM 10 /* enumeration */
|
||||
#define T_MOE 11 /* member of enumeration*/
|
||||
#define T_UCHAR 12 /* unsigned character */
|
||||
#define T_USHORT 13 /* unsigned short */
|
||||
#define T_UINT 14 /* unsigned integer */
|
||||
#define T_ULONG 15 /* unsigned long */
|
||||
#define T_LNGDBL 16 /* long double */
|
||||
|
||||
/*
|
||||
* derived types, in n_type
|
||||
*/
|
||||
#define DT_NON (0) /* no derived type */
|
||||
#define DT_PTR (1) /* pointer */
|
||||
#define DT_FCN (2) /* function */
|
||||
#define DT_ARY (3) /* array */
|
||||
|
||||
/*
|
||||
* type packing constants
|
||||
*/
|
||||
|
||||
#define IDA_N_BTMASK 017
|
||||
#define IDA_N_TMASK 060
|
||||
#define IDA_N_TMASK1 0300
|
||||
#define IDA_N_TMASK2 0360
|
||||
#define IDA_N_BTSHFT 4
|
||||
#define IDA_N_TSHIFT 2
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/* Basic Type of x */
|
||||
|
||||
#define IDA_BTYPE(x) ((x) & IDA_N_BTMASK)
|
||||
|
||||
/* Is x a pointer ? */
|
||||
|
||||
#define IDA_ISPTR(x) (((x) & IDA_N_TMASK) == (DT_PTR << IDA_N_BTSHFT))
|
||||
|
||||
/* Is x a function ? */
|
||||
|
||||
#define IDA_ISFCN(x) (((x) & IDA_N_TMASK) == (DT_FCN << IDA_N_BTSHFT))
|
||||
|
||||
/* Is x an array ? */
|
||||
|
||||
#define IDA_ISARY(x) (((x) & IDA_N_TMASK) == (DT_ARY << IDA_N_BTSHFT))
|
||||
|
||||
/* Is x a structure, union, or enumeration TAG? */
|
||||
|
||||
#define IDA_ISTAG(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG)
|
||||
|
||||
#define IDA_INCREF(x) ((((x)&~IDA_N_BTMASK)<<IDA_N_TSHIFT)|(DT_PTR<<IDA_N_BTSHFT)|(x&IDA_N_BTMASK))
|
||||
|
||||
#define IDA_DECREF(x) ((((x)>>IDA_N_TSHIFT)&~IDA_N_BTMASK)|((x)&IDA_N_BTMASK))
|
||||
|
||||
/*************************************************************************
|
||||
*
|
||||
* AUXILIARY ENTRY FORMAT
|
||||
*
|
||||
*************************************************************************/
|
||||
|
||||
typedef union auxent
|
||||
{
|
||||
struct
|
||||
{
|
||||
int32 x_tagndx; /* str, un, or enum tag indx */
|
||||
#define x_exptr x_tagndx /* exception table offset */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16 x_lnno; /* declaration line number */
|
||||
uint16 x_size; /* str, union, array size */
|
||||
} x_lnsz;
|
||||
int32 x_fsize; /* size of function */
|
||||
} x_misc;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{ /* if ISFCN, tag, or .bb */
|
||||
int32 x_lnnoptr; /* ptr to fcn line # */
|
||||
int32 x_endndx; /* entry ndx past block end */
|
||||
} x_fcn;
|
||||
struct
|
||||
{ /* if ISARY, up to 4 dimen. */
|
||||
uint16 x_dimen[DIMNUM];
|
||||
} x_ary;
|
||||
} x_fcnary;
|
||||
uint16 x_tvndx; /* tv index */
|
||||
} x_sym;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
int x_lnno;
|
||||
} x_lnsz;
|
||||
} x_misc;
|
||||
char pad[13];
|
||||
char x_auxtype;
|
||||
} x_sym64;
|
||||
|
||||
union
|
||||
{
|
||||
char x_fname[FILNMLEN];
|
||||
struct
|
||||
{
|
||||
uint32 x_zeroes;
|
||||
uint32 x_offset;
|
||||
} _x;
|
||||
} x_file;
|
||||
|
||||
struct
|
||||
{
|
||||
int32 x_scnlen; /* section length */
|
||||
uint16 x_nreloc; /* number of relocation entries */
|
||||
uint16 x_nlinno; /* number of line numbers */
|
||||
uint32 x_chksum; /* checksumm for comdat's */
|
||||
uint16 x_asscnt; /* section number to associate with */
|
||||
uchar x_select; /* comdat selection type */
|
||||
#define SSEL_NODUPL 1 // no duplicate
|
||||
#define SSEL_ANY 2 // select any
|
||||
#define SSEL_SIZE 3
|
||||
#define SSEL_EXACT 4 // by checksumm
|
||||
#define SSEL_ASSOC 5 // associative
|
||||
#define SSEL_LARGEST 6
|
||||
#define SSEL_NEWEST 7
|
||||
uchar __align__; /* for COFF+ only */
|
||||
uint16 x_asscnt_hi; /* for COFF+ only - hi part of x_asscnt */
|
||||
} x_scn; // always <= sizeof(SYMENT) :)
|
||||
|
||||
struct
|
||||
{
|
||||
int32 x_tvfill; /* tv fill value */
|
||||
uint16 x_tvlen; /* length of .tv */
|
||||
uint16 x_tvran[2]; /* tv range */
|
||||
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
|
||||
|
||||
/******************************************
|
||||
* RS/6000-specific auxent - last auxent for every external symbol
|
||||
******************************************/
|
||||
struct
|
||||
{
|
||||
int32 x_scnlen; /* csect length */
|
||||
int32 x_parmhash; /* parm type hash index */
|
||||
uint16 x_snhash; /* sect num with parm hash */
|
||||
uchar x_smtyp; /* symbol align and type */
|
||||
/* 0-4 - Log 2 of alignment */
|
||||
/* 5-7 - symbol type */
|
||||
#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */
|
||||
#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */
|
||||
/* Symbol type values: */
|
||||
#define XTY_ER 0 /* External reference */
|
||||
#define XTY_SD 1 /* Csect definition */
|
||||
#define XTY_LD 2 /* Label definition */
|
||||
#define XTY_CM 3 /* .BSS */
|
||||
#define XTY_EM 4 /* Error message */
|
||||
#define XTY_US 5 /* "Reserved for internal use" */
|
||||
uchar x_smclas; /* storage mapping class */
|
||||
#define XMC_PR 0 /* Read-only program code */
|
||||
#define XMC_RO 1 /* Read-only constant */
|
||||
#define XMC_DB 2 /* Read-only debug dictionary table */
|
||||
#define XMC_TC 3 /* Read-write general TOC entry */
|
||||
#define XMC_UA 4 /* Read-write unclassified */
|
||||
#define XMC_RW 5 /* Read-write data */
|
||||
#define XMC_GL 6 /* Read-only global linkage */
|
||||
#define XMC_XO 7 /* Read-only extended operation */
|
||||
#define XMC_SV 8 /* Read-only supervisor call */
|
||||
#define XMC_BS 9 /* Read-write BSS */
|
||||
#define XMC_DS 10 /* Read-write descriptor csect */
|
||||
#define XMC_UC 11 /* Read-write unnamed Fortran common */
|
||||
#define XMC_TI 12 /* Read-only traceback index csect */
|
||||
#define XMC_TB 13 /* Read-only traceback table csect */
|
||||
/* 14 ??? */
|
||||
#define XMC_TC0 15 /* Read-write TOC anchor */
|
||||
#define XMC_TD 16 /* Read-write data in TOC */
|
||||
int32 x_stab; /* dbx stab info index */
|
||||
uint16 x_snstab; /* sect num with dbx stab */
|
||||
} x_csect; /* csect definition information */\
|
||||
|
||||
/* XCOFF64 _csect */
|
||||
struct
|
||||
{
|
||||
uint32 x_scnlen_lo;
|
||||
int32 x_parmhash;
|
||||
uint16 x_snhash;
|
||||
uchar x_smtyp;
|
||||
uchar x_smclas;
|
||||
#define XMC_SV64 17
|
||||
#define XMC_SV2364 18
|
||||
int32 x_scnlen_hi;
|
||||
char pad;
|
||||
char x_auxtype;
|
||||
} x_csect64;
|
||||
|
||||
/******************************************
|
||||
* I960-specific *2nd* aux. entry formats
|
||||
******************************************/
|
||||
struct
|
||||
{
|
||||
#define x_stdindx x_stindx /* This is a very old typo that keeps getting propagated. */
|
||||
int32 x_stindx; /* sys. table entry */
|
||||
} x_sc; /* system call entry */
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 x_balntry; /* BAL entry point */
|
||||
} x_bal; /* BAL-callable function */
|
||||
|
||||
} AUXENT;
|
||||
|
||||
/* Defines for "special" symbols */
|
||||
|
||||
#if vax
|
||||
#define _ETEXT "_etext"
|
||||
#define _EDATA "_edata"
|
||||
#define _END "_end"
|
||||
#else
|
||||
#define _ETEXT "etext"
|
||||
#define _EDATA "edata"
|
||||
#define _END "end"
|
||||
#endif
|
||||
|
||||
#define _START "_start"
|
||||
|
||||
//================================================================================
|
||||
// ECOFF symbols
|
||||
//================================================================================
|
||||
|
||||
#define estNil 0 /* Nuthin' special */
|
||||
#define estGlobal 1 /* external symbol */
|
||||
#define estStatic 2 /* static */
|
||||
#define estParam 3 /* procedure argument */
|
||||
#define estLocal 4 /* local variable */
|
||||
#define estLabel 5 /* label */
|
||||
#define estProc 6 /* " " Procedure */
|
||||
#define estBlock 7 /* beginnning of block */
|
||||
#define estEnd 8 /* end (of anything) */
|
||||
#define estMember 9 /* member (of anything - struct/union/enum */
|
||||
#define estTypedef 10 /* type definition */
|
||||
#define estFile 11 /* file name */
|
||||
#define estRegReloc 12 /* register relocation */
|
||||
#define estForward 13 /* forwarding address */
|
||||
#define estStaticProc 14 /* load time only static procs */
|
||||
#define estConstant 15 /* const */
|
||||
#define estStaParam 16 /* Fortran static parameters */
|
||||
/* These new symbol types have been recently added to SGI machines. */
|
||||
#define estStruct 26 /* Beginning of block defining a struct type */
|
||||
#define estUnion 27 /* Beginning of block defining a union type */
|
||||
#define estEnum 28 /* Beginning of block defining an enum type */
|
||||
#define estIndirect 34 /* Indirect type specification */
|
||||
/* Pseudo-symbols - internal to debugger */
|
||||
#define estStr 60 /* string */
|
||||
#define estNumber 61 /* pure number (ie. 4 NOR 2+2) */
|
||||
#define estExpr 62 /* 2+2 vs. 4 */
|
||||
#define estType 63 /* post-coersion SER */
|
||||
#define estMax 64
|
||||
|
||||
#define escNil 0
|
||||
#define escText 1 /* text symbol */
|
||||
#define escData 2 /* initialized data symbol */
|
||||
#define escBss 3 /* un-initialized data symbol */
|
||||
#define escRegister 4 /* value of symbol is register number */
|
||||
#define escAbs 5 /* value of symbol is absolute */
|
||||
#define escUndefined 6 /* who knows? */
|
||||
#define escCdbLocal 7 /* variable's value is IN se->va.?? */
|
||||
#define escBits 8 /* this is a bit field */
|
||||
#define escCdbSystem 9 /* variable's value is IN CDB's address space */
|
||||
#define escDbx 9 /* overlap dbx internal use */
|
||||
#define escRegImage 10 /* register value saved on stack */
|
||||
#define escInfo 11 /* symbol contains debugger information */
|
||||
#define escUserStruct 12 /* address in struct user for current process */
|
||||
#define escSData 13 /* load time only small data */
|
||||
#define escSBss 14 /* load time only small common */
|
||||
#define escRData 15 /* load time only read only data */
|
||||
#define escVar 16 /* Var parameter (fortran,pascal) */
|
||||
#define escCommon 17 /* common variable */
|
||||
#define escSCommon 18 /* small common */
|
||||
#define escVarRegister 19 /* Var parameter in a register */
|
||||
#define escVariant 20 /* Variant record */
|
||||
#define escSUndefined 21 /* small undefined(external) data */
|
||||
#define escInit 22 /* .init section symbol */
|
||||
#define escBasedVar 23 /* Fortran or PL/1 ptr based var */
|
||||
#define escXData 24 /* exception handling data */
|
||||
#define escPData 25 /* Procedure section */
|
||||
#define escFini 26 /* .fini section */
|
||||
#define escRConst 27 /* .rconst section */
|
||||
#define escMax 32
|
||||
|
||||
struct ecoff_hdr
|
||||
{
|
||||
uint16 magic;
|
||||
#define ECOFF_SYM_MAGIC 0x1992
|
||||
uint16 vstamp;
|
||||
uint32 ilineMax;
|
||||
uint32 idnMax;
|
||||
uint32 ipdMax;
|
||||
uint32 isymMax;
|
||||
uint32 ioptMax;
|
||||
uint32 iauxMax;
|
||||
uint32 issMax;
|
||||
uint32 issExtMax;
|
||||
uint32 ifdMax;
|
||||
uint32 crfd;
|
||||
uint32 iextMax;
|
||||
uint64 cbLine;
|
||||
uint64 cbLineOffset;
|
||||
uint64 cbDnOffset;
|
||||
uint64 cbPdOffset;
|
||||
uint64 cbSymOffset;
|
||||
uint64 cbOptOffset;
|
||||
uint64 cbAuxOffset;
|
||||
uint64 cbSsOffset;
|
||||
uint64 cbSsExtOffset;
|
||||
uint64 cbFdOffset;
|
||||
uint64 cbRfdOffset;
|
||||
uint64 cbExtOffset;
|
||||
};
|
||||
|
||||
struct ecoff_fdr
|
||||
{
|
||||
uint64 f_adr;
|
||||
uint64 f_cbLineOffset;
|
||||
uint64 f_cbLine;
|
||||
uint64 f_cbSs;
|
||||
uint32 f_rss;
|
||||
uint32 f_issBase;
|
||||
uint32 f_isymBase;
|
||||
uint32 f_csym;
|
||||
uint32 f_ilineBase;
|
||||
uint32 f_cline;
|
||||
uint32 f_ioptBase;
|
||||
uint32 f_copt;
|
||||
uint32 f_ipdFirst;
|
||||
uint32 f_cpd;
|
||||
uint32 f_iauxBase;
|
||||
uint32 f_caux;
|
||||
uint32 f_rfdBase;
|
||||
uint32 f_crfd;
|
||||
uchar f_bits1;
|
||||
uchar f_bits2[3];
|
||||
uchar f_padding[4];
|
||||
};
|
||||
|
||||
/* Procedure descriptor external record */
|
||||
|
||||
struct ecoff_pdr
|
||||
{
|
||||
uint64 adr;
|
||||
uint64 cbLineOffset;
|
||||
uint32 isym;
|
||||
uint32 iline;
|
||||
uint32 regmask;
|
||||
uint32 regoffset;
|
||||
uint32 iopt;
|
||||
uint32 fregmask;
|
||||
uint32 fregoffset;
|
||||
uint32 frameoffset;
|
||||
uint32 lnLow;
|
||||
uint32 lnHigh;
|
||||
uchar gp_prologue;
|
||||
uchar bits1;
|
||||
uchar bits2;
|
||||
uchar localoff;
|
||||
uint16 framereg;
|
||||
uint16 pcreg;
|
||||
};
|
||||
|
||||
/* Line numbers */
|
||||
|
||||
struct ecoff_line
|
||||
{
|
||||
uint32 l_line;
|
||||
};
|
||||
|
||||
/* Symbol external record */
|
||||
|
||||
#define SYM_BITS1_ST_BIG 0xFC
|
||||
#define SYM_BITS1_ST_SH_BIG 2
|
||||
#define SYM_BITS1_ST_LITTLE 0x3F
|
||||
#define SYM_BITS1_ST_SH_LITTLE 0
|
||||
|
||||
#define SYM_BITS1_SC_BIG 0x03
|
||||
#define SYM_BITS1_SC_SH_LEFT_BIG 3
|
||||
#define SYM_BITS1_SC_LITTLE 0xC0
|
||||
#define SYM_BITS1_SC_SH_LITTLE 6
|
||||
|
||||
#define SYM_BITS2_SC_BIG 0xE0
|
||||
#define SYM_BITS2_SC_SH_BIG 5
|
||||
#define SYM_BITS2_SC_LITTLE 0x07
|
||||
#define SYM_BITS2_SC_SH_LEFT_LITTLE 2
|
||||
|
||||
#define SYM_BITS2_RESERVED_BIG 0x10
|
||||
#define SYM_BITS2_RESERVED_LITTLE 0x08
|
||||
|
||||
#define SYM_BITS2_INDEX_BIG 0x0F
|
||||
#define SYM_BITS2_INDEX_SH_LEFT_BIG 16
|
||||
#define SYM_BITS2_INDEX_LITTLE 0xF0
|
||||
#define SYM_BITS2_INDEX_SH_LITTLE 4
|
||||
|
||||
#define SYM_BITS3_INDEX_SH_LEFT_BIG 8
|
||||
#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4
|
||||
|
||||
#define SYM_BITS4_INDEX_SH_LEFT_BIG 0
|
||||
#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12
|
||||
|
||||
struct ecoff_sym
|
||||
{
|
||||
uint64 s_value;
|
||||
uint32 s_iss;
|
||||
uchar s_bits1;
|
||||
uchar s_bits2;
|
||||
uchar s_bits3;
|
||||
uchar s_bits4;
|
||||
uchar st(bool mf)
|
||||
{
|
||||
return mf
|
||||
? ((s_bits1 & SYM_BITS1_ST_BIG ) >> SYM_BITS1_ST_SH_BIG)
|
||||
: ((s_bits1 & SYM_BITS1_ST_LITTLE) >> SYM_BITS1_ST_SH_LITTLE);
|
||||
}
|
||||
uchar sc(bool mf)
|
||||
{
|
||||
return mf
|
||||
? (((s_bits1 & SYM_BITS1_SC_BIG ) << SYM_BITS1_SC_SH_LEFT_BIG)
|
||||
| ((s_bits2 & SYM_BITS2_SC_BIG ) >> SYM_BITS2_SC_SH_BIG))
|
||||
: (((s_bits1 & SYM_BITS1_SC_LITTLE) >> SYM_BITS1_SC_SH_LITTLE)
|
||||
| ((s_bits2 & SYM_BITS2_SC_LITTLE) << SYM_BITS2_SC_SH_LEFT_LITTLE));
|
||||
}
|
||||
uint32 index(bool mf)
|
||||
{
|
||||
return mf
|
||||
? (((s_bits2 & SYM_BITS2_INDEX_BIG) << SYM_BITS2_INDEX_SH_LEFT_BIG)
|
||||
| (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_BIG)
|
||||
| (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_BIG))
|
||||
: (((s_bits2 & SYM_BITS2_INDEX_LITTLE) >> SYM_BITS2_INDEX_SH_LITTLE)
|
||||
| (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_LITTLE)
|
||||
| (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_LITTLE));
|
||||
}
|
||||
};
|
||||
|
||||
/* The auxiliary type information is the same on all known ECOFF
|
||||
targets. The internal forms are
|
||||
defined in coff/sym.h, which was originally donated by MIPS
|
||||
Computer Systems. */
|
||||
|
||||
/* Type information external record */
|
||||
|
||||
struct ecoff_tir
|
||||
{
|
||||
uchar t_bits1;
|
||||
uchar t_tq45;
|
||||
uchar t_tq01;
|
||||
uchar t_tq23;
|
||||
bool fBitfield(bool mf) { return (t_bits1 & (mf ? 0x80 : 0x01)) != 0; }
|
||||
bool continued(bool mf) { return (t_bits1 & (mf ? 0x40 : 0x02)) != 0; }
|
||||
uchar bt(bool mf) { return mf ? (t_bits1 & 0x3F) >> 0 : (t_bits1 & 0xFC) >> 2; }
|
||||
uchar tq4(bool mf) { return mf ? (t_tq45 & 0xF0) >> 4 : (t_tq45 & 0x0F) >> 0; }
|
||||
uchar tq5(bool mf) { return mf ? (t_tq45 & 0x0F) >> 0 : (t_tq45 & 0xF0) >> 4; }
|
||||
uchar tq0(bool mf) { return mf ? (t_tq01 & 0xF0) >> 4 : (t_tq01 & 0x0F) >> 0; }
|
||||
uchar tq1(bool mf) { return mf ? (t_tq01 & 0x0F) >> 0 : (t_tq01 & 0xF0) >> 4; }
|
||||
uchar tq2(bool mf) { return mf ? (t_tq23 & 0xF0) >> 4 : (t_tq23 & 0x0F) >> 0; }
|
||||
uchar tq3(bool mf) { return mf ? (t_tq23 & 0x0F) >> 0 : (t_tq23 & 0xF0) >> 4; }
|
||||
};
|
||||
|
||||
/* Relative symbol external record */
|
||||
|
||||
struct ecoff_rndx
|
||||
{
|
||||
uchar r_bits[4];
|
||||
uint16 rfd(bool mf)
|
||||
{
|
||||
return mf
|
||||
? (r_bits[0] << 4) | ((r_bits[1] & 0xF0) >> 4)
|
||||
: (r_bits[0] << 0) | ((r_bits[1] & 0x0F) << 8);
|
||||
}
|
||||
uint32 index(bool mf)
|
||||
{
|
||||
return mf
|
||||
? ((r_bits[1] & 0x0F) << 16)
|
||||
| (r_bits[2] << 8)
|
||||
| (r_bits[3] << 0)
|
||||
: ((r_bits[1] & 0xF0) >> 4)
|
||||
| (r_bits[2] << 4)
|
||||
| (r_bits[3] << 12);
|
||||
}
|
||||
};
|
||||
|
||||
/* Auxiliary symbol information external record */
|
||||
|
||||
union ecoff_aux
|
||||
{
|
||||
ecoff_tir a_ti;
|
||||
ecoff_rndx a_rndx;
|
||||
uint32 a_dnLow;
|
||||
uint32 a_dnHigh;
|
||||
uint32 a_isym;
|
||||
uint32 a_iss;
|
||||
uint32 a_width;
|
||||
uint32 a_count;
|
||||
};
|
||||
|
||||
/* External symbol external record */
|
||||
|
||||
struct ecoff_ext
|
||||
{
|
||||
ecoff_sym es_asym;
|
||||
uchar es_bits1;
|
||||
uchar es_bits2[3];
|
||||
uint32 es_ifd;
|
||||
};
|
||||
|
||||
/* Dense numbers external record */
|
||||
|
||||
struct ecoff_dnr
|
||||
{
|
||||
uint32 d_rfd;
|
||||
uint32 d_index;
|
||||
};
|
||||
|
||||
/* Relative file descriptor */
|
||||
|
||||
struct ecoff_rfd
|
||||
{
|
||||
uint32 rfd;
|
||||
};
|
||||
|
||||
/* Optimizer symbol external record */
|
||||
|
||||
struct ecoff_opt
|
||||
{
|
||||
uchar o_bits1;
|
||||
uchar o_bits2;
|
||||
uchar o_bits3;
|
||||
uchar o_bits4;
|
||||
ecoff_rndx o_rndx;
|
||||
uint32 o_offset;
|
||||
uchar ot(void) { return o_bits1; }
|
||||
uint32 value(bool mf)
|
||||
{
|
||||
return mf
|
||||
? ((uint32(o_bits2) << 16)
|
||||
| (uint32(o_bits3) << 8)
|
||||
| (uint32(o_bits4) << 0))
|
||||
: ((uint32(o_bits2) << 0)
|
||||
| (uint32(o_bits3) << 8)
|
||||
| (uint32(o_bits4) << 16));
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// MIPS symbolic information
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
struct mips_ecoff_hdr
|
||||
{
|
||||
uint16 magic;
|
||||
#define MIPS_SYM_MAGIC 0x7002
|
||||
uint16 vstamp;
|
||||
uint32 ilineMax;
|
||||
uint32 cbLine;
|
||||
uint32 cbLineOffset;
|
||||
uint32 idnMax;
|
||||
uint32 cbDnOffset;
|
||||
uint32 ipdMax;
|
||||
uint32 cbPdOffset;
|
||||
uint32 isymMax;
|
||||
uint32 cbSymOffset;
|
||||
uint32 ioptMax;
|
||||
uint32 cbOptOffset;
|
||||
uint32 iauxMax;
|
||||
uint32 cbAuxOffset;
|
||||
uint32 issMax;
|
||||
uint32 cbSsOffset;
|
||||
uint32 issExtMax;
|
||||
uint32 cbSsExtOffset;
|
||||
uint32 ifdMax;
|
||||
uint32 cbFdOffset;
|
||||
uint32 crfd;
|
||||
uint32 cbRfdOffset;
|
||||
uint32 iextMax;
|
||||
uint32 cbExtOffset;
|
||||
};
|
||||
|
||||
struct mips_ecoff_fdr
|
||||
{
|
||||
uint32 f_adr;
|
||||
uint32 f_rss;
|
||||
uint32 f_issBase;
|
||||
uint32 f_cbSs;
|
||||
uint32 f_isymBase;
|
||||
uint32 f_csym;
|
||||
uint32 f_ilineBase;
|
||||
uint32 f_cline;
|
||||
uint32 f_ioptBase;
|
||||
uint32 f_copt;
|
||||
uint16 f_ipdFirst;
|
||||
uint16 f_cpd;
|
||||
uint32 f_iauxBase;
|
||||
uint32 f_caux;
|
||||
uint32 f_rfdBase;
|
||||
uint32 f_crfd;
|
||||
uchar f_bits1;
|
||||
uchar f_bits2[3];
|
||||
uint32 f_cbLineOffset;
|
||||
uint32 f_cbLine;
|
||||
};
|
||||
|
||||
/* Procedure descriptor external record */
|
||||
|
||||
struct mips_ecoff_pdr
|
||||
{
|
||||
uint32 adr;
|
||||
uint32 isym;
|
||||
uint32 iline;
|
||||
uint32 regmask;
|
||||
uint32 regoffset;
|
||||
uint32 iopt;
|
||||
uint32 fregmask;
|
||||
uint32 fregoffset;
|
||||
uint32 frameoffset;
|
||||
uint16 framereg;
|
||||
uint16 pcreg;
|
||||
uint32 lnLow;
|
||||
uint32 lnHigh;
|
||||
uint32 cbLineOffset;
|
||||
};
|
||||
|
||||
/* Line numbers */
|
||||
|
||||
struct mips_ecoff_line
|
||||
{
|
||||
uint32 l_line;
|
||||
};
|
||||
|
||||
/* Symbol external record */
|
||||
|
||||
struct mips_ecoff_sym
|
||||
{
|
||||
uint32 s_iss;
|
||||
uint32 s_value;
|
||||
uchar s_bits1;
|
||||
uchar s_bits2;
|
||||
uchar s_bits3;
|
||||
uchar s_bits4;
|
||||
uchar st(bool mf)
|
||||
{
|
||||
return mf
|
||||
? ((s_bits1 & SYM_BITS1_ST_BIG ) >> SYM_BITS1_ST_SH_BIG)
|
||||
: ((s_bits1 & SYM_BITS1_ST_LITTLE) >> SYM_BITS1_ST_SH_LITTLE);
|
||||
}
|
||||
uchar sc(bool mf)
|
||||
{
|
||||
return mf
|
||||
? (((s_bits1 & SYM_BITS1_SC_BIG ) << SYM_BITS1_SC_SH_LEFT_BIG)
|
||||
| ((s_bits2 & SYM_BITS2_SC_BIG ) >> SYM_BITS2_SC_SH_BIG))
|
||||
: (((s_bits1 & SYM_BITS1_SC_LITTLE) >> SYM_BITS1_SC_SH_LITTLE)
|
||||
| ((s_bits2 & SYM_BITS2_SC_LITTLE) << SYM_BITS2_SC_SH_LEFT_LITTLE));
|
||||
}
|
||||
uint32 index(bool mf)
|
||||
{
|
||||
return mf
|
||||
? (((s_bits2 & SYM_BITS2_INDEX_BIG) << SYM_BITS2_INDEX_SH_LEFT_BIG)
|
||||
| (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_BIG)
|
||||
| (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_BIG))
|
||||
: (((s_bits2 & SYM_BITS2_INDEX_LITTLE) >> SYM_BITS2_INDEX_SH_LITTLE)
|
||||
| (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_LITTLE)
|
||||
| (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_LITTLE));
|
||||
}
|
||||
};
|
||||
|
||||
#define mips_ecoff_aux ecoff_aux
|
||||
|
||||
/* External symbol external record */
|
||||
|
||||
struct mips_ecoff_ext
|
||||
{
|
||||
uchar es_bits1;
|
||||
uchar es_bits2;
|
||||
uint16 es_ifd;
|
||||
mips_ecoff_sym es_asym;
|
||||
};
|
||||
|
||||
#define mips_ecoff_dnr ecoff_dnr
|
||||
#define mips_ecoff_rfd ecoff_rfd
|
||||
#define mips_ecoff_opt ecoff_opt
|
||||
|
||||
/* segment information */
|
||||
struct ic_seginfo_t
|
||||
{
|
||||
const ida_sym_t *sym = nullptr; // comdat symbol
|
||||
ea_t start = BADADDR; // segment start address, BADADDR - not loaded
|
||||
adiff_t delta = 0; // difference between the loaded address
|
||||
// and address in the file
|
||||
ea_t paddr = 0; // s_paddr from the segment descriptor
|
||||
};
|
||||
DECLARE_TYPE_AS_MOVABLE(ic_seginfo_t);
|
||||
struct ic_seginfos_t : public qvector<ic_seginfo_t> {};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool is_arm_switcher(const char *name)
|
||||
{
|
||||
return strncmp(name, "$CODE", 5) == 0
|
||||
&& (name[5] == '1' || name[5] == '3')
|
||||
&& (name[6] == '6' || name[6] == '2')
|
||||
&& name[7] == '\0';
|
||||
}
|
||||
|
||||
struct i960_sym_t;
|
||||
struct coff_sym_ex_t;
|
||||
struct ida_filhdr_t;
|
||||
struct ida_scnhdr_t;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class ida_syms_t
|
||||
{
|
||||
struct coff_vars_t &ctx;
|
||||
qstring str_table; // standard COFF string table (includes size in first 4 bytes)
|
||||
qstring dtable; // XCOFF debug table (does not include size)
|
||||
|
||||
void from_coff960(const i960_sym_t *pc, uint nsyms, bool coff_hdr_mf);
|
||||
void from_bigcoff(const coff_sym_ex_t *pc, uint nsyms, bool coff_hdr_mf);
|
||||
void from_xcoff64(const coff_sym64_t *pc, uint nsyms, bool coff_hdr_mf);
|
||||
void from_coffsym(const coff_sym_t *pc, uint nsyms, bool coff_hdr_mf);
|
||||
public:
|
||||
qvector<ida_sym_t> symtab;
|
||||
|
||||
ida_syms_t(coff_vars_t &_ctx) : ctx(_ctx) {}
|
||||
bool str_table_from_file(linput_t *li, bool coff_hdr_mf);
|
||||
bool str_table_from_mem(const void *buf, size_t bufsize, bool coff_hdr_mf);
|
||||
bool load_from_file(
|
||||
linput_t *li,
|
||||
const ida_filhdr_t &fh,
|
||||
bool coff_hdr_mf);
|
||||
bool load_from_mem(const void *symbuf, size_t bufsize, uint32 nsyms, bool coff_hdr_mf);
|
||||
#if !defined(COMPILE_DBG_LOADER)
|
||||
void load_xcoff_debug_table(linput_t *li, const qvector<ida_scnhdr_t> &sechdrs);
|
||||
#endif
|
||||
const ida_sym_t *load_external_coff_symbols(linput_t *li, ida_filhdr_t &hf, bool mf);
|
||||
|
||||
void qclear()
|
||||
{
|
||||
str_table.qclear();
|
||||
dtable.qclear();
|
||||
symtab.qclear();
|
||||
}
|
||||
|
||||
void copy_from_str_table(char *buf, size_t bufsz, uint32 off, bool use_dtable = false) const;
|
||||
const char *get_segment_name(const char *name, size_t fixlen, char *buffer, size_t bufsize, uint32 f_magic) const;
|
||||
bool getaux(uint symidx, AUXENT &aux, uint &n_aux) const;
|
||||
char *getname(uint symidx, char *buf, size_t bufsize) const;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* _H_SYMS */
|
||||
1310
idasdk76/ldr/dos/cv.hpp
Normal file
1310
idasdk76/ldr/dos/cv.hpp
Normal file
File diff suppressed because it is too large
Load Diff
762
idasdk76/ldr/dos/dos.cpp
Normal file
762
idasdk76/ldr/dos/dos.cpp
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* This Loader Module is written by Ilfak Guilfanov and
|
||||
* rewriten by Yury Haron
|
||||
*
|
||||
*/
|
||||
/*
|
||||
L O A D E R for MS-DOS file format's
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include <exehdr.h>
|
||||
#include <setjmp.h>
|
||||
#include <typeinf.hpp>
|
||||
#include "dos_ovr.h"
|
||||
#include "cv.hpp"
|
||||
|
||||
static const char fn_ovr[] = "MS-DOS executable (perhaps overlayed)",
|
||||
fn_exe[] = "MS-DOS executable (EXE)",
|
||||
fn_drv[] = "MS-DOS SYS-file (perhaps device driver)";
|
||||
const char e_exe[] = "exe";
|
||||
|
||||
static jmp_buf jmpb;
|
||||
|
||||
#define R_ss 18 // this comes from intel.hpp
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *filename)
|
||||
{
|
||||
static int order = 0;
|
||||
if ( order >= 4 )
|
||||
return 0;
|
||||
|
||||
uint32 fLen = qlsize(li);
|
||||
const char *file_ext = get_file_ext(filename);
|
||||
if ( file_ext == NULL )
|
||||
file_ext = "";
|
||||
|
||||
exehdr E;
|
||||
*processor = "metapc";
|
||||
switch ( order )
|
||||
{
|
||||
case 0:
|
||||
if ( fLen <= sizeof(E) )
|
||||
{
|
||||
order = 3; // check for com
|
||||
break;
|
||||
}
|
||||
|
||||
CASSERT(sizeof(E) >= 16);
|
||||
lread(li, &E, sizeof(E));
|
||||
if ( E.exe_ident != EXE_ID && E.exe_ident != EXE_ID2
|
||||
|| E.HdrSize*16 < sizeof(E) )
|
||||
{
|
||||
order = 2; // check for drv
|
||||
break;
|
||||
}
|
||||
if ( fLen < E.HdrSize*16 )
|
||||
return 0;
|
||||
if ( E.ReloCnt != 0 )
|
||||
{
|
||||
if ( E.TablOff + (E.ReloCnt*4) > fLen
|
||||
|| E.TablOff != 0 && E.TablOff < sizeof(E)
|
||||
|| E.TablOff == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ( E.CalcEXE_Length() < fLen - E.HdrSize*16
|
||||
&& PrepareOverlayType(li, &E) != ovr_noexe )
|
||||
{
|
||||
*fileformatname = fn_ovr;
|
||||
++order;
|
||||
return f_EXE | ACCEPT_CONTINUE;
|
||||
}
|
||||
// no break
|
||||
case 1:
|
||||
*fileformatname = fn_exe;
|
||||
order = 5; // done
|
||||
return f_EXE;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( ++order == 3 )
|
||||
{
|
||||
if ( strieq(file_ext, "sys") || strieq(file_ext, "drv") )
|
||||
{
|
||||
*fileformatname = fn_drv;
|
||||
return f_DRV | ACCEPT_CONTINUE;
|
||||
}
|
||||
order++; // 4
|
||||
}
|
||||
|
||||
if ( strieq(file_ext, "com") )
|
||||
{ // com files must be readable
|
||||
// on wince, file .exe files are unreadable. we do not want them to
|
||||
// be detected as com files
|
||||
qlseek(li, 0);
|
||||
if ( qlread(li, &fLen, 1) == 1 )
|
||||
{
|
||||
*fileformatname = "MS-DOS COM-file";
|
||||
return f_COM;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
NORETURN void errstruct(void)
|
||||
{
|
||||
if ( ask_yn(ASKBTN_CANCEL,
|
||||
"HIDECANCEL\n"
|
||||
"Bad file structure or read error.\n"
|
||||
"Proceed with the loaded infomration?") <= ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
longjmp(jmpb, 1);
|
||||
#ifdef __CODEGEARC__
|
||||
exit(0); // suppress compiler error
|
||||
#endif
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
int CheckCtrlBrk(void)
|
||||
{
|
||||
if ( user_cancelled() )
|
||||
{
|
||||
if ( ask_yn(ASKBTN_NO,
|
||||
"HIDECANCEL\n"
|
||||
"Do you really want to abort loading?") > ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
clr_cancelled();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void add_segm_by_selector(sel_t base, const char *sclass)
|
||||
{
|
||||
segment_t *ptr = get_segm_by_sel(base);
|
||||
|
||||
if ( ptr == NULL || ptr->sel != base )
|
||||
{
|
||||
ea_t ea = sel2ea(base);
|
||||
if ( ea > inf_get_omax_ea() )
|
||||
inf_set_omax_ea(ea);
|
||||
|
||||
segment_t s;
|
||||
s.sel = base;
|
||||
s.start_ea = sel2ea(base);
|
||||
s.end_ea = inf_get_omax_ea();
|
||||
s.align = saRelByte;
|
||||
s.comb = sclass != NULL && strcmp(sclass, "STACK") == 0 ? scStack : scPub;
|
||||
add_segm_ex(&s, NULL, sclass, ADDSEG_SPARSE | ADDSEG_NOSREG);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
//
|
||||
// For all addresses in relocation table:
|
||||
// add 'delta'
|
||||
// if ( dosegs ) then make segments
|
||||
//
|
||||
static void doRelocs(int16 delta, bool dosegs, netnode ovr_info)
|
||||
{
|
||||
|
||||
if ( ovr_info == BADNODE )
|
||||
return;
|
||||
|
||||
fixup_data_t fd(FIXUP_SEG16);
|
||||
for ( ea_t xEA = ovr_info.altfirst(); xEA != BADADDR; xEA = ovr_info.altnext(xEA) )
|
||||
{
|
||||
show_addr(xEA);
|
||||
|
||||
uint16 curval = get_word(xEA);
|
||||
uint16 base = curval + delta;
|
||||
if ( base < curval && delta > 0 )
|
||||
{
|
||||
ask_for_feedback("%a: fixup overflow; skipping fixup processing", xEA);
|
||||
break;
|
||||
}
|
||||
put_word(xEA, base);
|
||||
fd.sel = base;
|
||||
fd.set(xEA);
|
||||
if ( dosegs )
|
||||
add_segm_by_selector(base, NULL);
|
||||
CheckCtrlBrk();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create_msdos_segments(bool com_mode, netnode ovr_info)
|
||||
{
|
||||
// msg("Creating segments...\n");
|
||||
add_segm_by_selector(find_selector(inf_get_start_cs()), CLASS_CODE);
|
||||
if ( com_mode ) // COM/DRV
|
||||
{
|
||||
set_segm_start(inf_get_omin_ea(), inf_get_omin_ea(), SEGMOD_KILL);
|
||||
inf_set_min_ea(inf_get_omin_ea());
|
||||
|
||||
segment_t *s = getseg(inf_get_min_ea());
|
||||
if ( s )
|
||||
{
|
||||
s->set_comorg(); // i display ORG directive
|
||||
s->update();
|
||||
}
|
||||
}
|
||||
if ( inf_get_start_ss() != BADSEL && inf_get_start_ss() != inf_get_start_cs() )
|
||||
add_segm_by_selector(inf_get_start_ss(), CLASS_STACK);
|
||||
else // specify the sp value for the first segment
|
||||
set_default_sreg_value(get_segm_by_sel(inf_get_start_cs()), R_ss, inf_get_start_cs());
|
||||
doRelocs(inf_get_baseaddr(), true, ovr_info);
|
||||
|
||||
ea_t ea = inf_get_omin_ea();
|
||||
ea_t omea = inf_get_omax_ea();
|
||||
for ( int i = 0; ea < omea; )
|
||||
{
|
||||
segment_t *sptr = getnseg(i);
|
||||
if ( sptr == NULL || ea < sptr->start_ea )
|
||||
{
|
||||
msg("Dummy segment at 0x%a (next segment at 0x%a)\n",
|
||||
ea,
|
||||
sptr == NULL ? BADADDR : sptr->start_ea);
|
||||
add_segm_by_selector(unsigned(ea>>4), "DUMMY");
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = sptr->end_ea;
|
||||
if ( !is_mapped(ea) )
|
||||
ea = next_addr(ea);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool pos_read(linput_t *li, uint32 pos, void *buf, size_t size)
|
||||
{
|
||||
qlseek(li, pos);
|
||||
return qlread(li, buf, size) != size;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static ea_t FindDseg(void)
|
||||
{
|
||||
ea_t dea = to_ea(inf_get_start_cs(), inf_get_start_ip());
|
||||
|
||||
if ( get_byte(dea) == 0x9A ) // call far
|
||||
{
|
||||
dea = to_ea(sel2para(get_word(dea+3)), get_word(dea+1));
|
||||
inf_set_strtype(STRTYPE_PASCAL);
|
||||
}
|
||||
//
|
||||
// Borland startup
|
||||
//
|
||||
uchar code = get_byte(dea);
|
||||
uchar reg = code & 7;
|
||||
if ( (code & ~7) == 0xB8 // mov reg, ????
|
||||
&& ((get_byte(dea+3) == 0x8E
|
||||
&& ((code=get_byte(dea+4)) & ~7) == 0xD8 // mov ds, reg
|
||||
&& (code & 7) == reg)
|
||||
|| (get_byte(dea+3) == 0x2E // mov cs:@DGROUP, reg
|
||||
&& get_byte(dea+4) == 0x89
|
||||
&& ((code = get_byte(dea+5)) & 0x8F) == 6
|
||||
&& ((code>>3) & 7) == reg)) )
|
||||
{
|
||||
segment_t *s = get_segm_by_sel(get_word(dea + 1));
|
||||
return s == NULL ? BADADDR : s->start_ea;
|
||||
}
|
||||
//
|
||||
// Watcom startup
|
||||
//
|
||||
if ( get_byte(dea) == 0xE9 ) // jmp ???
|
||||
{
|
||||
dea = dea + 3 + get_word(dea + 1);
|
||||
if ( get_byte(dea + 0) == 0xFB // sti
|
||||
&& get_byte(dea + 1) == 0xB9 ) // mov cx, ???
|
||||
{
|
||||
segment_t *s = get_segm_by_sel(get_word(dea + 2));
|
||||
return s == NULL ? BADADDR : s->start_ea;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Generic: find copyright notice
|
||||
//
|
||||
static const char *const copyr[] =
|
||||
{
|
||||
" - Copyright",
|
||||
// "Borland C++ - Copyright 1991 Borland Intl.",
|
||||
// "Turbo-C - Copyright (c) 1988 Borland Intl.",
|
||||
// "Turbo C - Copyright 1989 Borland Intl.",
|
||||
// "Turbo C++ - Copyright 1990 Borland Intl.",
|
||||
// "MS Run-Time Library - Copyright (c)",
|
||||
NULL
|
||||
};
|
||||
for ( const char *const *p = copyr; *p != NULL; ++p )
|
||||
{
|
||||
msg("Looking for '%s'...\n", *p);
|
||||
ea_t dataea = bin_search2(inf_get_min_ea(),
|
||||
inf_get_max_ea(),
|
||||
(uchar *)*p,
|
||||
NULL,
|
||||
strlen(*p),
|
||||
BIN_SEARCH_CASE|BIN_SEARCH_FORWARD);
|
||||
if ( dataea != BADADDR )
|
||||
return dataea;
|
||||
}
|
||||
return BADADDR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void setup_default_ds_register(sel_t ds_value)
|
||||
{
|
||||
segment_t *dseg;
|
||||
|
||||
if ( ds_value != BADSEL )
|
||||
{
|
||||
dseg = get_segm_by_sel(ds_value);
|
||||
goto setname;
|
||||
}
|
||||
msg("Searching for the data segment...\n");
|
||||
switch ( inf_get_filetype() )
|
||||
{
|
||||
case f_EXE: // Find default data seg
|
||||
{
|
||||
ea_t dataea = FindDseg();
|
||||
if ( dataea == BADADDR )
|
||||
return;
|
||||
dseg = getseg(dataea);
|
||||
if ( dseg == NULL )
|
||||
return;
|
||||
}
|
||||
dseg->align = saRelPara;
|
||||
ds_value = dseg->sel;
|
||||
setname:
|
||||
set_segm_class(dseg, CLASS_DATA);
|
||||
set_segm_name(dseg, "dseg");
|
||||
break;
|
||||
case f_COM:
|
||||
ds_value = find_selector(inf_get_start_cs());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
msg("Default DS register: 0x%*a\n", 4, ds_value);
|
||||
set_default_dataseg(ds_value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
void idaapi load_file(linput_t *li, ushort neflag, const char *fileformatname)
|
||||
{
|
||||
exehdr E;
|
||||
netnode ovr_info = BADNODE;
|
||||
volatile int type = 0; // volatile because of setjmp()
|
||||
volatile sel_t dseg = BADSEL;
|
||||
volatile o_type ovr_type = ovr_noexe;
|
||||
|
||||
processor_t &ph = PH;
|
||||
if ( setjmp(jmpb) == 0 )
|
||||
{
|
||||
set_processor_type("metapc", SETPROC_LOADER);
|
||||
|
||||
type = strieq(fileformatname, fn_ovr) ? 3
|
||||
: strieq(fileformatname, fn_exe) ? 2
|
||||
: strieq(fileformatname, fn_drv) ? 1
|
||||
: 0;
|
||||
|
||||
clr_cancelled();
|
||||
|
||||
uval_t start_off;
|
||||
uval_t fcoresize;
|
||||
cm_t cm = inf_get_cc_cm() & CM_CC_MASK;
|
||||
if ( type < 2 ) // COM/DRV
|
||||
{
|
||||
inf_set_cc_cm(cm | C_PC_SMALL);
|
||||
if ( !type ) // f_COM
|
||||
{
|
||||
inf_set_start_ip(0x100);
|
||||
inf_set_min_ea(to_ea(inf_get_baseaddr(), inf_get_start_ip()));
|
||||
}
|
||||
else
|
||||
{ // f_DRV
|
||||
inf_set_start_ip(BADADDR);
|
||||
inf_set_min_ea(to_ea(inf_get_baseaddr(), 0 /*binoff*/));
|
||||
// binoff has no sense for COM/DRV
|
||||
}
|
||||
inf_set_start_cs(inf_get_baseaddr());
|
||||
start_off = 0;
|
||||
fcoresize = qlsize(li);
|
||||
inf_set_max_ea(inf_get_min_ea() + fcoresize);
|
||||
}
|
||||
else
|
||||
{ // EXE (/OVR)
|
||||
inf_set_cc_cm(cm | C_PC_LARGE);
|
||||
lread(li, &E, sizeof(E));
|
||||
if ( !E.ReloCnt
|
||||
&& ask_yn(ASKBTN_YES,
|
||||
"HIDECANCEL\nPossibly packed file, continue?") <= ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
inf_set_start_ss(E.ReloSS);
|
||||
inf_set_start_cs(E.ReloCS);
|
||||
inf_set_start_sp(E.ExeSP);
|
||||
inf_set_start_ip(E.ExeIP);
|
||||
// take into account pointers like FFF0:0100
|
||||
// FFF0 should be treated as signed in this case
|
||||
if ( inf_get_start_cs() >= 0xFFF0 || inf_get_start_ss() >= 0xFFF0 )
|
||||
{
|
||||
if ( inf_get_baseaddr() < 0x10 )
|
||||
inf_set_baseaddr(0x10);
|
||||
if ( inf_get_start_cs() >= 0xFFF0 )
|
||||
inf_set_start_cs(short(inf_get_start_cs()));
|
||||
if ( inf_get_start_ss() >= 0xFFF0 )
|
||||
inf_set_start_ss(short(inf_get_start_ss()));
|
||||
}
|
||||
inf_set_start_ss(inf_get_start_ss() + inf_get_baseaddr());
|
||||
inf_set_start_cs(inf_get_start_cs() + inf_get_baseaddr());
|
||||
inf_set_min_ea(to_ea(inf_get_baseaddr(), 0));
|
||||
fcoresize = E.CalcEXE_Length();
|
||||
|
||||
ovr_info.create(LDR_INFO_NODE);
|
||||
ovr_info.set((char *)&E, sizeof(E));
|
||||
|
||||
// i Check for file size
|
||||
uint32 fsize = qlsize(li) - E.HdrSize*16;
|
||||
if ( fcoresize > fsize )
|
||||
fcoresize = fsize;
|
||||
if ( type == 2
|
||||
&& fcoresize < fsize
|
||||
&& ask_yn(ASKBTN_YES,
|
||||
"HIDECANCEL\n"
|
||||
"The input file has extra information at the end\n"
|
||||
"(tail %Xh, loaded %ah), continue?",
|
||||
fsize,
|
||||
fcoresize) <= ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
inf_set_max_ea(inf_get_min_ea() + fcoresize);
|
||||
|
||||
ea_t stackEA = to_ea(inf_get_start_ss(), inf_get_start_sp());
|
||||
if ( inf_get_max_ea() < stackEA )
|
||||
inf_set_max_ea(stackEA);
|
||||
msg("Reading relocation table...\n");
|
||||
if ( E.ReloCnt )
|
||||
{
|
||||
qlseek(li, E.TablOff);
|
||||
for ( int i = 0; i < E.ReloCnt; ++i )
|
||||
{
|
||||
ushort buf[2];
|
||||
|
||||
lread(li, buf, sizeof(buf));
|
||||
|
||||
ea_t xEA = to_ea((ushort)(inf_get_baseaddr() + buf[1]), buf[0]); // we need ushort() here!
|
||||
if ( xEA >= inf_get_max_ea() )
|
||||
errstruct();
|
||||
ovr_info.altset(xEA, 1);
|
||||
}
|
||||
}
|
||||
start_off = E.HdrSize * 16;
|
||||
// i preset variable for overlay loading
|
||||
if ( type == 3 )
|
||||
ovr_type = PrepareOverlayType(li, &E);
|
||||
}
|
||||
// next 2 strings for create_msdos_segments & CppOverlays
|
||||
inf_set_omin_ea(inf_get_min_ea());
|
||||
inf_set_omax_ea(inf_get_max_ea());
|
||||
|
||||
file2base(li, start_off, inf_get_min_ea(), inf_get_min_ea() + fcoresize,
|
||||
FILEREG_PATCHABLE);
|
||||
|
||||
if ( ovr_type != ovr_cpp )
|
||||
{
|
||||
if ( type == 3 || (neflag & NEF_SEGS) )
|
||||
create_msdos_segments((type <= 1), ovr_info);
|
||||
else
|
||||
doRelocs(inf_get_baseaddr(), false, ovr_info);
|
||||
}
|
||||
|
||||
create_filename_cmt();
|
||||
add_pgm_cmt("Base Address: %ah Range: %ah-%ah Loaded length: %ah",
|
||||
inf_get_baseaddr(), inf_get_min_ea(), inf_get_max_ea(), fcoresize);
|
||||
if ( type >= 2 )
|
||||
{ // f_EXE
|
||||
linput_t *volatile lio = NULL;
|
||||
add_pgm_cmt("Entry Point : %a:%a", inf_get_start_cs(), inf_get_start_ip());
|
||||
if ( type == 2 // && E.CalcEXE_Length() < qlsize(li) - E.HdrSize*16
|
||||
&& (lio = CheckExternOverlays()) != NULL )
|
||||
{
|
||||
++type;
|
||||
}
|
||||
if ( type != 3 )
|
||||
{
|
||||
ovr_info.altset(-1, type); // EXE without overlays
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( ovr_type )
|
||||
{
|
||||
case ovr_pascal:
|
||||
lio = li;
|
||||
// fallthrough
|
||||
case ovr_noexe:
|
||||
LoadPascalOverlays(lio);
|
||||
if ( ovr_type == ovr_noexe )
|
||||
close_linput(lio);
|
||||
break;
|
||||
|
||||
case ovr_cpp:
|
||||
dseg = LoadCppOverlays(li);
|
||||
doRelocs(inf_get_baseaddr(), false, ovr_info);
|
||||
break;
|
||||
|
||||
case ovr_ms:
|
||||
dseg = LoadMsOverlays(li, E.Overlay == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setup_default_ds_register(dseg); // former SRcreate()
|
||||
if ( dseg != BADSEL && ovr_type == ovr_ms )
|
||||
{
|
||||
segment_t *s = get_segm_by_sel(find_selector(inf_get_start_cs()));
|
||||
if ( s != NULL )
|
||||
set_default_sreg_value(s, ph.reg_data_sreg, s->sel);
|
||||
}
|
||||
inf_set_start_ea((inf_get_start_ip() == BADADDR)
|
||||
? BADADDR
|
||||
: to_ea(sel2para(inf_get_start_cs()), inf_get_start_ip()));
|
||||
if ( inf_get_start_ip() != BADADDR )
|
||||
{
|
||||
uval_t val;
|
||||
if ( type < 2 )
|
||||
val = find_selector(inf_get_start_cs()); // COM/DRV
|
||||
else if ( get_str_type_code(inf_get_strtype()) == STRTYPE_PASCAL )
|
||||
val = get_sreg(inf_get_start_ea(), ph.reg_data_sreg); // i set in [srareaovl.cpp]FindDseg
|
||||
else
|
||||
val = inf_get_baseaddr() - 0x10;
|
||||
split_sreg_range(inf_get_start_ea(), ph.reg_data_sreg, val, SR_autostart, true);
|
||||
}
|
||||
|
||||
if ( inf_get_filetype() == f_COM )
|
||||
{
|
||||
inf_set_lowoff(0x100);
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for the debug information
|
||||
char debug_magic[4];
|
||||
qlseek(li, -8, SEEK_END);
|
||||
lread(li, debug_magic, 4);
|
||||
if ( is_codeview_magic(debug_magic) )
|
||||
load_dbg_dbginfo(NULL, li);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int expand_file(FILE *fp, uint32 pos)
|
||||
{
|
||||
// return chsize(li, pos) || qfseek(fp, pos, SEEK_SET);
|
||||
// but qchsize(), which does not fill with zeroes.
|
||||
uint32 curpos = qftell(fp);
|
||||
QASSERT(20041, curpos <= pos);
|
||||
while ( curpos < pos )
|
||||
{
|
||||
if ( qfputc(0, fp) == EOF )
|
||||
return 0;
|
||||
++curpos;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// generate binary file.
|
||||
//
|
||||
int idaapi save_file(FILE *fp, const char * /*fileformatname*/)
|
||||
{
|
||||
int retcode;
|
||||
uint32 codeoff;
|
||||
netnode ovr_info(LDR_INFO_NODE, 0, 0);
|
||||
|
||||
if ( fp == NULL )
|
||||
return ovr_info == BADNODE || ovr_info.altval(-1) == 2;
|
||||
|
||||
if ( ovr_info != BADNODE ) // f_EXE
|
||||
{
|
||||
exehdr E;
|
||||
ovr_info.valobj(&E, sizeof(E));
|
||||
|
||||
if ( qfwrite(fp, &E, sizeof(E)) != sizeof(E) )
|
||||
return 0;
|
||||
if ( E.ReloCnt )
|
||||
{
|
||||
if ( !expand_file(fp, E.TablOff) )
|
||||
return 0;
|
||||
|
||||
for ( uval_t x = ovr_info.altfirst();
|
||||
x != BADADDR;
|
||||
x = ovr_info.altnext(x) )
|
||||
{
|
||||
ushort buf[2];
|
||||
|
||||
buf[1] = ushort((x >> 4) - inf_get_baseaddr());
|
||||
buf[0] = ushort(x) & 0xF;
|
||||
if ( qfwrite(fp, buf, sizeof(buf)) != sizeof(buf) )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
codeoff = E.HdrSize * 16;
|
||||
if ( !expand_file(fp, codeoff) )
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
codeoff = 0; // f_COM, f_DRV
|
||||
}
|
||||
|
||||
doRelocs(-inf_get_baseaddr(), 0, ovr_info);
|
||||
retcode = base2file(fp, codeoff, inf_get_omin_ea(), inf_get_omax_ea());
|
||||
doRelocs(inf_get_baseaddr(), 0, ovr_info);
|
||||
return retcode;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static int idaapi move_segm(ea_t from, ea_t to, asize_t /*size*/, const char * /*fileformatname*/)
|
||||
{
|
||||
// Before relocating, we need all of the relocation entries, which were
|
||||
// part of the original executable file and consequently stored in our
|
||||
// private loader node.
|
||||
netnode ovr_info(LDR_INFO_NODE, 0, 0);
|
||||
if ( ovr_info == BADNODE )
|
||||
{
|
||||
// Can't find our private loader node.
|
||||
msg("Couldn't find dos.ldr node, assuming file has no relocations.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( from == BADADDR )
|
||||
{
|
||||
// The entire program is being rebased.
|
||||
// In this case, 'to' actually contains a delta value; the number of bytes
|
||||
// forward (positive) or backward (negative) that the whole database is
|
||||
// being moved.
|
||||
int32 delta = to;
|
||||
|
||||
// If the delta is not a multiple of 16 bytes, we can't reliably
|
||||
// relocate the executable.
|
||||
if ( (delta % 16) != 0 )
|
||||
{
|
||||
warning("DOS images can only be relocated to 16-byte boundaries.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fixup the relocation entry netnode. It contains entries that point
|
||||
// to locations that needed fixups when the image was located at its
|
||||
// old address. Change the entries so that they point to the appropriate
|
||||
// places in the new image location.
|
||||
ea_t current_base = uint32(inf_get_baseaddr() << 4);
|
||||
ea_t new_base = current_base + delta;
|
||||
ovr_info.altshift(current_base, new_base, inf_get_privrange_start_ea());
|
||||
|
||||
// remember bases for later remapping of segment regs
|
||||
std::map<ea_t, ea_t> segmap;
|
||||
|
||||
// Now that the relocation entries point to the correct spots, go fix
|
||||
// those spots up so that they point to the correct places.
|
||||
doRelocs(delta >> 4, false, ovr_info);
|
||||
|
||||
// IDA has adjusted all segment start and end addresses to cover their
|
||||
// new effective address ranges, but we, the loader, must finish the
|
||||
// job by rebasing each segment.
|
||||
for ( int i = 0; i < get_segm_qty(); ++i )
|
||||
{
|
||||
segment_t *seg = getnseg(i);
|
||||
ea_t curbase = get_segm_base(seg); // Returns base in EA
|
||||
ea_t newbase = curbase + delta;
|
||||
set_segm_base(seg, newbase >> 4); // Expects base in Paragraphs
|
||||
segmap[curbase >> 4] = newbase >> 4;
|
||||
seg->update();
|
||||
}
|
||||
|
||||
// fix up segment registers
|
||||
// rebase segment registers
|
||||
processor_t &ph = PH;
|
||||
for ( int sr = 0; sr < SREG_NUM; ++sr )
|
||||
{
|
||||
int sra_num = get_sreg_ranges_qty(ph.reg_first_sreg + sr);
|
||||
for ( int i = 0; i < sra_num; ++i )
|
||||
{
|
||||
sreg_range_t sra;
|
||||
if ( !getn_sreg_range(&sra, sr, i) )
|
||||
break;
|
||||
sel_t reg = sra.val;
|
||||
if ( reg != BADSEL )
|
||||
{
|
||||
std::map<ea_t, ea_t>::const_iterator p = segmap.find(reg);
|
||||
if ( p != segmap.end() )
|
||||
split_sreg_range(sra.start_ea, ph.reg_first_sreg + sr, p->second, SR_auto, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record the new image base address.
|
||||
inf_set_baseaddr(new_base >> 4);
|
||||
set_imagebase(new_base);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// LOADER DESCRIPTION BLOCK
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
loader_t LDSC =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
// loader flags
|
||||
0,
|
||||
|
||||
// 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.
|
||||
save_file,
|
||||
|
||||
// take care of a moved segment (fix up relocations, for example)
|
||||
move_segm,
|
||||
NULL,
|
||||
};
|
||||
1068
idasdk76/ldr/dos/dos_ovr.cpp
Normal file
1068
idasdk76/ldr/dos/dos_ovr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
85
idasdk76/ldr/dos/dos_ovr.h
Normal file
85
idasdk76/ldr/dos/dos_ovr.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.00
|
||||
* Copyright (c) 1990-94 by Ilfak Guilfanov. (2:5020/209@fidonet)
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DOS_OVR_H_
|
||||
#define _DOS_OVR_H_
|
||||
|
||||
// the following structures are 1-byte aligned (!)
|
||||
#pragma pack(push,1)
|
||||
|
||||
struct fbov_t
|
||||
{
|
||||
ushort fb;
|
||||
#define FB_MAGIC 0x4246
|
||||
ushort ov;
|
||||
#define OV_MAGIC 0x564F
|
||||
uint32 ovrsize;
|
||||
uint32 exeinfo;
|
||||
int32 segnum;
|
||||
};
|
||||
|
||||
struct seginfo_t
|
||||
{
|
||||
ushort seg;
|
||||
ushort maxoff; // FFFF - unknown
|
||||
ushort flags;
|
||||
#define SI_COD 0x0001
|
||||
#define SI_OVR 0x0002
|
||||
#define SI_DAT 0x0004
|
||||
ushort minoff;
|
||||
};
|
||||
|
||||
struct stub_t
|
||||
{
|
||||
uchar CDh; // 0
|
||||
uchar intnum; // 1
|
||||
ushort memswap; // 2
|
||||
int32 fileoff; // 4
|
||||
ushort codesize; // 8
|
||||
ushort relsize; // 10
|
||||
ushort nentries; // 12
|
||||
ushort prevstub; // 14
|
||||
#define STUBUNK_SIZE (0x20-0x10)
|
||||
uchar unknown[STUBUNK_SIZE];
|
||||
};
|
||||
|
||||
struct ovrentry_t
|
||||
{
|
||||
ushort int3f;
|
||||
ushort off;
|
||||
char segc;
|
||||
};
|
||||
|
||||
CASSERT(sizeof(ovrentry_t) == 5);
|
||||
|
||||
struct ms_entry
|
||||
{
|
||||
uchar CDh;
|
||||
uchar intnum; // normally 3Fh
|
||||
ushort ovr_index;
|
||||
ushort entry_off;
|
||||
};
|
||||
|
||||
bool pos_read(linput_t *fp, uint32 pos, void *buf, size_t size);
|
||||
int CheckCtrlBrk(void);
|
||||
void add_segm_by_selector(sel_t base, const char *sclass);
|
||||
extern const char e_exe[];
|
||||
//
|
||||
enum o_type { ovr_noexe, ovr_pascal, ovr_cpp, ovr_ms };
|
||||
|
||||
o_type PrepareOverlayType(linput_t *fp, exehdr *E);
|
||||
linput_t *CheckExternOverlays(void);
|
||||
sel_t LoadCppOverlays(linput_t *fp);
|
||||
sel_t LoadMsOverlays(linput_t *fp, bool PossibleDynamic);
|
||||
void LoadPascalOverlays(linput_t *fp);
|
||||
|
||||
NORETURN void errstruct(void);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
24
idasdk76/ldr/dos/makefile
Normal file
24
idasdk76/ldr/dos/makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
PROC=dos
|
||||
O1=dos_ovr
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)dos$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \
|
||||
$(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 ../idaldr.h \
|
||||
cv.hpp dos.cpp dos_ovr.h
|
||||
$(F)dos_ovr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \
|
||||
$(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)struct.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \
|
||||
dos_ovr.cpp dos_ovr.h
|
||||
348
idasdk76/ldr/dump/dump.cpp
Normal file
348
idasdk76/ldr/dump/dump.cpp
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2001 by Ilfak Guilfanov (ig@datarescue.com)
|
||||
* http://www.datarescue.com
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int make_words(char *line, char **words, int maxwords)
|
||||
{
|
||||
while ( qisspace(*line) )
|
||||
line++;
|
||||
int i;
|
||||
for ( i=0; *line && i < maxwords; i++ )
|
||||
{
|
||||
words[i] = line;
|
||||
while ( !qisspace(*line) && *line != '\0' )
|
||||
line++;
|
||||
if ( *line != '\0' )
|
||||
*line++ = '\0';
|
||||
while ( qisspace(*line) )
|
||||
line++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline uint32 hex(char *&word)
|
||||
{
|
||||
return strtoul(word, &word, 16);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline uint32 oct(char *&word)
|
||||
{
|
||||
return strtoul(word, &word, 8);
|
||||
}
|
||||
|
||||
#define FAILED \
|
||||
do \
|
||||
{ \
|
||||
deb(IDA_DEBUG_LDR, \
|
||||
"failed at %d (input file line %d)\n", \
|
||||
__LINE__, \
|
||||
nl); \
|
||||
return 0; \
|
||||
} while ( false )
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
char line[MAXSTR];
|
||||
char *words[MAXSTR];
|
||||
|
||||
// We try to interpret the input file as a text
|
||||
// file with a dump format, i.e. all lines should look like
|
||||
|
||||
// 00000020: 59 69 74 54-55 B6 3E F7-D6 B9 C9 B9-45 E6 A4 52
|
||||
// 0020: 59 69 74 54 55 B6 3E F7 D6 B9 C9 B9 45 E6 A4 52
|
||||
// 1000: 12 23 34 56 78
|
||||
// 0100: 31 C7 1D AF 32 04 1E 32 05 1E 3C 32 07 1E 21 D9
|
||||
// 12 23 34 56 78
|
||||
|
||||
// and similar lines
|
||||
// We allow non-ascii characters at the end of the line
|
||||
// We skip empty lines
|
||||
|
||||
ssize_t p0len = -1; // length of the first word's hex part
|
||||
char w0sep[10]; // separator after the first word
|
||||
w0sep[0] = '\0';
|
||||
int nl = 0;
|
||||
int nontrivial_line_count = 0;
|
||||
bool no_more_lines = false;
|
||||
bool has_star = false;
|
||||
uint32 adr, oldadr=0;
|
||||
while ( qlgets(line, sizeof(line), li) )
|
||||
{
|
||||
nl++;
|
||||
strrpl(line, '-', ' ');
|
||||
int nw = make_words(line, words, qnumber(words));
|
||||
if ( line[0] == ';' || line[0] == '#' || nw == 0 )
|
||||
{
|
||||
if ( has_star )
|
||||
FAILED;
|
||||
continue;
|
||||
}
|
||||
if ( no_more_lines )
|
||||
FAILED;
|
||||
// od -x format may contain '*' lines which mean repetition
|
||||
if ( strcmp(words[0], "*") == 0 && nw == 1 )
|
||||
{
|
||||
if ( nontrivial_line_count == 0 )
|
||||
FAILED;
|
||||
if ( has_star )
|
||||
FAILED;
|
||||
has_star = true;
|
||||
continue;
|
||||
}
|
||||
has_star = false;
|
||||
nontrivial_line_count++;
|
||||
// the first word must be a number (more than one digit)
|
||||
char *ptr = words[0];
|
||||
adr = hex(ptr);
|
||||
ssize_t p0 = ptr - words[0];
|
||||
if ( p0 <= 1 || p0 > 16 )
|
||||
FAILED;
|
||||
if ( nontrivial_line_count > 1 && p0 < p0len )
|
||||
FAILED;
|
||||
p0len = p0;
|
||||
// take the separator from the first line
|
||||
if ( nontrivial_line_count == 1 )
|
||||
{
|
||||
qstrncpy(w0sep, ptr, sizeof(w0sep));
|
||||
while ( *ptr )
|
||||
if ( strchr(":>-.", *ptr++) == NULL )
|
||||
FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( strcmp(w0sep, ptr) != 0 )
|
||||
FAILED;
|
||||
}
|
||||
bool haspref = p0len >= 4 || w0sep[0] != '\0';
|
||||
if ( haspref )
|
||||
{
|
||||
// if the line contains only the address, then don't accept lines anymore
|
||||
if ( nw == 1 )
|
||||
{
|
||||
if ( nontrivial_line_count == 1 )
|
||||
FAILED;
|
||||
no_more_lines = true;
|
||||
if ( adr <= oldadr )
|
||||
FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the remaining words should be numbers with at least 1 position
|
||||
// (at least the second word should be so)
|
||||
ptr = words[1];
|
||||
hex(ptr);
|
||||
if ( ptr == words[1] )
|
||||
FAILED;
|
||||
}
|
||||
}
|
||||
oldadr = adr;
|
||||
}
|
||||
if ( nontrivial_line_count == 0 || has_star )
|
||||
FAILED;
|
||||
|
||||
*fileformatname = "Dump file";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static uchar bytes[MAXSTR/2];
|
||||
static bool iscode;
|
||||
static sel_t sel;
|
||||
static ea_t sea;
|
||||
static ea_t eea;
|
||||
static ushort neflag;
|
||||
|
||||
static void copy(const ea_t ea, const ea_t top)
|
||||
{
|
||||
if ( sea == BADADDR )
|
||||
{
|
||||
if ( neflag & NEF_SEGS )
|
||||
{
|
||||
const char *sname = iscode ? "CODE" : "DATA";
|
||||
sel = setup_selector(0);
|
||||
add_segm(sel, ea, top, sname, sname);
|
||||
}
|
||||
sea = ea;
|
||||
eea = top;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( eea < top )
|
||||
{ // if the gap > 256KB, use sparse storage
|
||||
int flags = top - eea > 256 * 1024 ? SEGMOD_SPARSE : 0;
|
||||
eea = top;
|
||||
set_segm_end(sea, eea, flags);
|
||||
}
|
||||
}
|
||||
mem2base(bytes, ea, top, -1);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort _neflag, const char * /*fileformatname*/)
|
||||
{
|
||||
char line[MAXSTR];
|
||||
char *words[MAXSTR];
|
||||
|
||||
neflag = _neflag;
|
||||
iscode = (neflag & NEF_CODE) != 0;
|
||||
sel = BADSEL;
|
||||
sea = BADADDR;
|
||||
ea_t ea = 0;
|
||||
ea_t top= 0;
|
||||
bool octpref = false;
|
||||
bool octnum = false;
|
||||
size_t fill = 0;
|
||||
|
||||
// Since we made all the checks in accept_file,
|
||||
// here we don't repeat them
|
||||
|
||||
size_t max_p0len = 0;
|
||||
char w0sep[10]; // separator after the first word
|
||||
w0sep[0] = '\0';
|
||||
int nontrivial_line_count = 0;
|
||||
while ( qlgets(line, sizeof(line), li) )
|
||||
{
|
||||
strrpl(line, '-', ' ');
|
||||
if ( line[0] == ';' || line[0] == '#' )
|
||||
continue;
|
||||
int n = make_words(line, words, qnumber(words));
|
||||
if ( n == 0 )
|
||||
continue;
|
||||
nontrivial_line_count++;
|
||||
ssize_t bi;
|
||||
// od -x format may contain '*' lines which mean repetition
|
||||
if ( strcmp(words[0], "*") == 0 && n == 1 )
|
||||
{
|
||||
fill = size_t(top - ea);
|
||||
octpref = true; // od -x have octal prefixes
|
||||
continue;
|
||||
}
|
||||
// the first word must be a number (more than one digit)
|
||||
char *ptr = words[0];
|
||||
uint32 w0 = octpref ? oct(ptr) : hex(ptr);
|
||||
// length of the first word's hex part
|
||||
size_t p0len = ptr - words[0];
|
||||
if ( p0len > max_p0len )
|
||||
max_p0len = p0len;
|
||||
|
||||
// take the separator from the first line
|
||||
if ( nontrivial_line_count == 1 )
|
||||
qstrncpy(w0sep, ptr, sizeof(w0sep));
|
||||
|
||||
// process '*' and fill the gap
|
||||
if ( fill > 0 )
|
||||
{
|
||||
while ( top < w0 )
|
||||
{
|
||||
ea = top;
|
||||
top = ea + fill;
|
||||
copy(ea, top);
|
||||
}
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
if ( w0sep[0] != '\0' || p0len >= 4 )
|
||||
{
|
||||
if ( nontrivial_line_count > 1 && !octpref && top != w0 )
|
||||
{
|
||||
// strange, the sequence is not contiguous
|
||||
// check if the prefixes are octal (od -x)
|
||||
ptr = words[0];
|
||||
if ( oct(ptr) == top )
|
||||
{
|
||||
octpref = true;
|
||||
ptr = words[0];
|
||||
w0 = oct(ptr);
|
||||
}
|
||||
}
|
||||
ea = w0;
|
||||
idx = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = top;
|
||||
}
|
||||
for ( bi=0; idx < n; idx++ ) //lint !e443
|
||||
{
|
||||
ptr = words[idx];
|
||||
if ( nontrivial_line_count == 1 && !octnum && strlen(ptr) == 6 )
|
||||
{
|
||||
oct(ptr);
|
||||
if ( ptr-words[idx] == 6 )
|
||||
octnum = true;
|
||||
ptr = words[idx];
|
||||
// msg("ptr=%s octnum=%d\n", ptr, octnum);
|
||||
}
|
||||
uint32 b = octnum ? oct(ptr) : hex(ptr);
|
||||
ssize_t nc = ptr - words[idx];
|
||||
if ( nc < 2 )
|
||||
{
|
||||
// we tolerate one-letter separators between numbers
|
||||
if ( words[idx][1] == '\0' && strchr("\xA6|-:", words[idx][0]) != NULL )
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
nc /= octnum ? 3 : 2; // number of bytes
|
||||
*(uint32 *)&bytes[bi] = b;
|
||||
bi += nc;
|
||||
}
|
||||
top = ea + bi;
|
||||
copy(ea, top);
|
||||
}
|
||||
|
||||
if ( neflag & NEF_SEGS )
|
||||
{
|
||||
size_t bitness = eea >= 0x10000 || max_p0len > 4 ? 1 : 0; // 32/16
|
||||
#ifdef __EA64__
|
||||
if ( eea >= ea_t(0x100000000ull) || max_p0len > 8 )
|
||||
bitness = 2; // 64
|
||||
#endif
|
||||
if ( bitness != 0 )
|
||||
{
|
||||
set_segm_addressing(getseg(sea), bitness);
|
||||
inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT);
|
||||
}
|
||||
set_default_dataseg(sel);
|
||||
}
|
||||
if ( (neflag & NEF_RELOAD) == 0 )
|
||||
create_filename_cmt();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
loader_t LDSC =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
LDRF_REQ_PROC // requires the target processor to the set
|
||||
| LDRF_RELOAD, // supports reloading the input file
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
13
idasdk76/ldr/dump/makefile
Normal file
13
idasdk76/ldr/dump/makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
PROC=dump
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)dump$(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 ../idaldr.h dump.cpp
|
||||
104
idasdk76/ldr/elf/common.cpp
Normal file
104
idasdk76/ldr/elf/common.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA)
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* E-mail: ig@datarescue.com
|
||||
* ELF binary loader.
|
||||
* Copyright (c) 1995-2006 by Iouri Kharon.
|
||||
* E-mail: yjh@styx.cabel.net
|
||||
*
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <idp.hpp>
|
||||
|
||||
#include "elfbase.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Functions common for EFD & DEBUGGER
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static bool dummy_error_handler(const reader_t &, reader_t::errcode_t, ...)
|
||||
{
|
||||
// ignore all errors
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool is_elf_file(linput_t *li)
|
||||
{
|
||||
reader_t reader(li);
|
||||
reader.set_handler(dummy_error_handler);
|
||||
return reader.read_ident() && reader.read_header();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline bool can_be_solaris(reader_t &reader)
|
||||
{
|
||||
switch ( reader.get_header().e_machine )
|
||||
{
|
||||
case EM_SPARC:
|
||||
case EM_SPARC32PLUS:
|
||||
case EM_SPARC64:
|
||||
case EM_386:
|
||||
case EM_486:
|
||||
case EM_X86_64:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int elf_machine_2_proc_module_id(reader_t &reader)
|
||||
{
|
||||
int id = -1;
|
||||
switch ( reader.get_header().e_machine )
|
||||
{
|
||||
#define CASE(E_ID, P_ID) case EM_##E_ID: id = PLFM_##P_ID; break
|
||||
CASE(ARM, ARM);
|
||||
CASE(SH, SH);
|
||||
CASE(PPC, PPC);
|
||||
CASE(PPC64, PPC);
|
||||
CASE(860, I860);
|
||||
CASE(68K, 68K);
|
||||
CASE(MIPS, MIPS);
|
||||
CASE(CISCO7200, MIPS);
|
||||
CASE(CISCO3620, MIPS);
|
||||
CASE(386, 386);
|
||||
CASE(486, 386);
|
||||
CASE(X86_64, 386);
|
||||
CASE(SPARC, SPARC);
|
||||
CASE(SPARC32PLUS, SPARC);
|
||||
CASE(SPARC64, SPARC);
|
||||
CASE(ALPHA, ALPHA);
|
||||
CASE(IA64, IA64);
|
||||
CASE(H8300, H8);
|
||||
CASE(H8300H, H8);
|
||||
CASE(H8S, H8);
|
||||
CASE(H8500, H8);
|
||||
CASE(V850, NEC_V850X);
|
||||
CASE(NECV850, NEC_V850X);
|
||||
CASE(PARISC, HPPA);
|
||||
CASE(6811, 6800);
|
||||
CASE(6812, MC6812);
|
||||
CASE(I960, I960);
|
||||
CASE(ARC, ARC);
|
||||
CASE(ARCOMPACT, ARC);
|
||||
CASE(ARC_COMPACT2, ARC);
|
||||
CASE(M32R, M32R);
|
||||
CASE(ST9, ST9);
|
||||
CASE(FR, FR);
|
||||
CASE(AVR, AVR);
|
||||
CASE(SPU, SPU);
|
||||
CASE(C166, C166);
|
||||
CASE(M16C, M16C);
|
||||
CASE(MN10200, MN102L00);
|
||||
// CASE(MN10300, MN103L00); // FIXME: Dunno what to do, here.
|
||||
// CASE(MCORE, MCORE); // FIXME: PLFM_MCORE still defined in mcore/reg.cpp
|
||||
CASE(S390, S390);
|
||||
#undef CASE
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
3249
idasdk76/ldr/elf/elf.h
Normal file
3249
idasdk76/ldr/elf/elf.h
Normal file
File diff suppressed because it is too large
Load Diff
1014
idasdk76/ldr/elf/elfbase.h
Normal file
1014
idasdk76/ldr/elf/elfbase.h
Normal file
File diff suppressed because it is too large
Load Diff
542
idasdk76/ldr/elf/elfr_arm.h
Normal file
542
idasdk76/ldr/elf/elfr_arm.h
Normal file
@@ -0,0 +1,542 @@
|
||||
#ifndef __ELFR_ARM_H__
|
||||
#define __ELFR_ARM_H__
|
||||
|
||||
#ifndef __ELFBASE_H__
|
||||
#include "elfbase.h"
|
||||
#endif
|
||||
|
||||
// relocation field - word32 with HIGH BYTE FIRST!!!
|
||||
// A- from Elf32_Rela
|
||||
// B- Loading address of shared object (REAL section when symbol defined)
|
||||
// (not) G- offset into global objet table
|
||||
// (not) GOT- adress of global object table
|
||||
// (not) L- linkage table entry
|
||||
// P- place of storage unit (computed using r_offset)
|
||||
// S- value of symbol
|
||||
enum elf_RTYPE_arm
|
||||
{
|
||||
|
||||
R_ARM_NONE = 0, // No reloc
|
||||
R_ARM_PC24 = 1, // S-P+A (relative 26 bit branch)
|
||||
R_ARM_ABS32 = 2, // S+A
|
||||
R_ARM_REL32 = 3, // S-P+A
|
||||
R_ARM_LDR_PC_G0 = 4, // S-P+A
|
||||
R_ARM_ABS16 = 5, // S+A
|
||||
R_ARM_ABS12 = 6, // S+A
|
||||
R_ARM_THM_ABS5 = 7, // S+A
|
||||
R_ARM_ABS8 = 8, // S+A
|
||||
R_ARM_SBREL32 = 9, // S-B+A
|
||||
R_ARM_THM_CALL = 10, // S-P+A
|
||||
R_ARM_THM_PC8 = 11, // S-P+A
|
||||
R_ARM_BREL_ADJ = 12, // S-B+A
|
||||
R_ARM_TLS_DESC = 13, //
|
||||
R_ARM_THM_SWI8 = 14, // S+A (obsolete)
|
||||
R_ARM_XPC25 = 15, // S-P+A (obsolete)
|
||||
R_ARM_THM_XPC22 = 16, // S-P+A (obsolete)
|
||||
R_ARM_TLS_DTPMOD32 = 17, /* ID of module containing symbol */
|
||||
R_ARM_TLS_DTPOFF32 = 18, /* Offset in TLS block */
|
||||
R_ARM_TLS_TPOFF32 = 19, /* Offset in static TLS block */
|
||||
// linux-specific
|
||||
R_ARM_COPY = 20, // none (copy symbol at runtime)
|
||||
R_ARM_GLOB_DAT = 21, // S (create .got entry)
|
||||
R_ARM_JUMP_SLOT = 22, // S (create .plt entry)
|
||||
R_ARM_RELATIVE = 23, // B+A (adjust by programm base)
|
||||
R_ARM_GOTOFF32 = 24, // S+A-GOT (32bit offset to .got)
|
||||
R_ARM_BASE_PREL = 25, // B+A-P
|
||||
R_ARM_GOT_BREL = 26, // G+A-GOT (32bit .got entry)
|
||||
R_ARM_PLT32 = 27, // L+A-P (32bit .plt entry)
|
||||
|
||||
R_ARM_CALL = 28,
|
||||
R_ARM_JUMP24 = 29,
|
||||
R_ARM_THM_JUMP24 = 30, // ((S + A) | T) - P
|
||||
R_ARM_BASE_ABS = 31, // B + A
|
||||
R_ARM_ALU_PCREL7_0 = 32,
|
||||
R_ARM_ALU_PCREL15_8 = 33,
|
||||
R_ARM_ALU_PCREL23_15 = 34,
|
||||
R_ARM_LDR_SBREL_11_0 = 35,
|
||||
R_ARM_ALU_SBREL_19_12 = 36,
|
||||
R_ARM_ALU_SBREL_27_20 = 37,
|
||||
R_ARM_TARGET1 = 38,
|
||||
R_ARM_ROSEGREL32 = 39,
|
||||
R_ARM_V4BX = 40,
|
||||
R_ARM_TARGET2 = 41,
|
||||
R_ARM_PREL31 = 42,
|
||||
R_ARM_MOVW_ABS_NC = 43, // Static ARM (S + A) | T
|
||||
R_ARM_MOVT_ABS = 44, // Static ARM S + A
|
||||
R_ARM_MOVW_PREL_NC = 45, // Static ARM ((S + A) | T) - P
|
||||
R_ARM_MOVT_PREL = 46, // Static ARM S + A - P
|
||||
R_ARM_THM_MOVW_ABS_NC = 47, // Static Thumb32 (S + A) | T
|
||||
R_ARM_THM_MOVT_ABS = 48, // Static Thumb32 S + A
|
||||
R_ARM_THM_MOVW_PREL_NC= 49, // Static Thumb32 ((S + A) | T) - P
|
||||
R_ARM_THM_MOVT_PREL = 50, // Static Thumb32 S + A - P
|
||||
R_ARM_THM_JUMP19 = 51, // Static Thumb32 ((S + A) | T) - P
|
||||
R_ARM_THM_JUMP6 = 52, // Static Thumb16 S + A - P
|
||||
R_ARM_THM_ALU_PREL_11_0= 53, // Static Thumb32 ((S + A) | T) - Pa
|
||||
R_ARM_THM_PC12 = 54, // Static Thumb32 S + A - Pa
|
||||
R_ARM_ABS32_NOI = 55, // Static Data S + A
|
||||
R_ARM_REL32_NOI = 56, // Static Data S + A - P
|
||||
R_ARM_ALU_PC_G0_NC = 57, // Static ARM ((S + A) | T) - P
|
||||
R_ARM_ALU_PC_G0 = 58, // Static ARM ((S + A) | T) - P
|
||||
R_ARM_ALU_PC_G1_NC = 59, // Static ARM ((S + A) | T) - P
|
||||
R_ARM_ALU_PC_G1 = 60, // Static ARM ((S + A) | T) - P
|
||||
R_ARM_ALU_PC_G2 = 61, // Static ARM ((S + A) | T) - P
|
||||
R_ARM_LDR_PC_G1 = 62, // Static ARM S + A - P
|
||||
R_ARM_LDR_PC_G2 = 63, // Static ARM S + A - P
|
||||
R_ARM_LDRS_PC_G0 = 64, // Static ARM S + A - P
|
||||
|
||||
R_ARM_LDRS_PC_G1 = 65, // Static ARM S + A - P
|
||||
R_ARM_LDRS_PC_G2 = 66, // Static ARM S + A - P
|
||||
R_ARM_LDC_PC_G0 = 67, // Static ARM S + A - P
|
||||
R_ARM_LDC_PC_G1 = 68, // Static ARM S + A - P
|
||||
R_ARM_LDC_PC_G2 = 69, // Static ARM S + A - P
|
||||
R_ARM_ALU_SB_G0_NC = 70, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_ALU_SB_G0 = 71, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_ALU_SB_G1_NC = 72, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_ALU_SB_G1 = 73, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_ALU_SB_G2 = 74, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_LDR_SB_G0 = 75, // Static ARM S + A - B(S)
|
||||
R_ARM_LDR_SB_G1 = 76, // Static ARM S + A - B(S)
|
||||
R_ARM_LDR_SB_G2 = 77, // Static ARM S + A - B(S)
|
||||
R_ARM_LDRS_SB_G0 = 78, // Static ARM S + A - B(S)
|
||||
R_ARM_LDRS_SB_G1 = 79, // Static ARM S + A - B(S)
|
||||
R_ARM_LDRS_SB_G2 = 80, // Static ARM S + A - B(S)
|
||||
R_ARM_LDC_SB_G0 = 81, // Static ARM S + A - B(S)
|
||||
R_ARM_LDC_SB_G1 = 82, // Static ARM S + A - B(S)
|
||||
R_ARM_LDC_SB_G2 = 83, // Static ARM S + A - B(S)
|
||||
R_ARM_MOVW_BREL_NC = 84, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_MOVT_BREL = 85, // Static ARM S + A - B(S)
|
||||
R_ARM_MOVW_BREL = 86, // Static ARM ((S + A) | T) - B(S)
|
||||
R_ARM_THM_MOVW_BREL_NC = 87, // Static Thumb32 ((S + A) | T) - B(S)
|
||||
R_ARM_THM_MOVT_BREL = 88, // Static Thumb32 S + A - B(S)
|
||||
R_ARM_THM_MOVW_BREL = 89, // Static Thumb32 ((S + A) | T) - B(S)
|
||||
R_ARM_TLS_GOTDESC = 90, // Static Data
|
||||
R_ARM_TLS_CALL = 91, // Static ARM
|
||||
R_ARM_TLS_DESCSEQ = 92, // Static ARM TLS relaxation
|
||||
R_ARM_THM_TLS_CALL = 93, // Static Thumb32
|
||||
R_ARM_PLT32_ABS = 94, // Static Data PLT(S) + A
|
||||
|
||||
R_ARM_GOT_ABS = 95, // G+A
|
||||
R_ARM_GOT_PREL = 96, // G+A-P
|
||||
R_ARM_GOT_BREL12 = 97, // G+A-GOT
|
||||
R_ARM_GOTOFF12 = 98, // S+A-GOT
|
||||
R_ARM_GOTRELAX = 99,
|
||||
R_ARM_GNU_VTENTRY = 100,
|
||||
R_ARM_GNU_VTINHERIT = 101,
|
||||
|
||||
R_ARM_THM_PC11 = 102, /* Cygnus extension to abi: Thumb unconditional branch. */
|
||||
R_ARM_THM_PC9 = 103, /* Cygnus extension to abi: Thumb conditional branch. */
|
||||
R_ARM_THM_JUMP11 = 102, // Static Thumb16 S + A - P
|
||||
R_ARM_THM_JUMP8 = 103, // Static Thumb16 S + A - P
|
||||
R_ARM_TLS_GD32 = 104, // Static Data GOT(S) + A - P
|
||||
R_ARM_TLS_LDM32 = 105, // Static Data GOT(S) + A - P
|
||||
R_ARM_TLS_LDO32 = 106, // Static Data S + A - TLS
|
||||
R_ARM_TLS_IE32 = 107, // Static Data GOT(S) + A - P
|
||||
R_ARM_TLS_LE32 = 108, // Static Data S + A - tp
|
||||
R_ARM_TLS_LDO12 = 109, // Static ARM S + A - TLS
|
||||
R_ARM_TLS_LE12 = 110, // Static ARM S + A - tp
|
||||
R_ARM_TLS_IE12GP = 111, // Static ARM GOT(S) + A - GOT_ORG
|
||||
R_ARM_PRIVATE_0 = 112, // Private (n = 0, 1, ... 15)
|
||||
R_ARM_PRIVATE_1 = 113,
|
||||
R_ARM_PRIVATE_2 = 114,
|
||||
R_ARM_PRIVATE_3 = 115,
|
||||
R_ARM_PRIVATE_4 = 116,
|
||||
R_ARM_PRIVATE_5 = 117,
|
||||
R_ARM_PRIVATE_6 = 118,
|
||||
R_ARM_PRIVATE_7 = 119,
|
||||
R_ARM_PRIVATE_8 = 120,
|
||||
R_ARM_PRIVATE_9 = 121,
|
||||
R_ARM_PRIVATE_10 = 122,
|
||||
R_ARM_PRIVATE_11 = 123,
|
||||
R_ARM_PRIVATE_12 = 124,
|
||||
R_ARM_PRIVATE_13 = 125,
|
||||
R_ARM_PRIVATE_14 = 126,
|
||||
R_ARM_PRIVATE_15 = 127,
|
||||
R_ARM_ME_TOO = 128, // Obsolete
|
||||
R_ARM_THM_TLS_DESCSEQ16 = 129,// Static Thumb16
|
||||
R_ARM_THM_TLS_DESCSEQ32 = 130,// Static Thumb32
|
||||
R_ARM_THM_GOT_BREL12 = 131, // GOT entry relative to GOT origin, 12 bit (Thumb32 LDR).
|
||||
R_ARM_THM_ALU_ABS_G0_NC = 132,
|
||||
R_ARM_THM_ALU_ABS_G1_NC = 133,
|
||||
R_ARM_THM_ALU_ABS_G2_NC = 134,
|
||||
R_ARM_THM_ALU_ABS_G3_NC = 135,
|
||||
|
||||
// 136 - 139 Unallocated
|
||||
// 140 - 159 Dynamic Reserved for future allocation
|
||||
|
||||
R_ARM_IRELATIVE = 160,
|
||||
|
||||
// 161 - 255 Unallocated
|
||||
|
||||
//
|
||||
// ATT: R_ARM_RXPC25 used ONLY in OLD_ABI (+ 15 OTHER relocs!)
|
||||
// dynamic sections only
|
||||
R_ARM_RXPC25 = 249, // (BLX) call between segments
|
||||
//
|
||||
R_ARM_RSBREL32 = 250, // (Word) SBrelative offset
|
||||
R_ARM_THM_RPC22 = 251, // (Thumb BL/BLX) call between segments
|
||||
R_ARM_RREL32 = 252, // (Word) inter-segment offset
|
||||
R_ARM_RABS32 = 253, // (Word) Target segment displacement
|
||||
R_ARM_RPC24 = 254, // (BL/BLX) call between segment
|
||||
R_ARM_RBASE = 255 // segment being relocated
|
||||
};
|
||||
|
||||
// X is the result of a relocation operation, before any masking or bit-selection
|
||||
// Page(expr) is the page address of the expression expr, defined as (expr & ~0xFFF)
|
||||
// GOT is the address of the Global Offset Table
|
||||
// GDAT(S+A) represents a 64-bit entry in the GOT for address S+A
|
||||
// G(expr) is the address of the GOT entry for the expression expr
|
||||
// Delta(S) if S is a normal symbol, resolves to the difference between
|
||||
// the static link address of S and the execution address of S.
|
||||
// If S is the null symbol (ELF symbol index 0), resolves to the difference
|
||||
// between the static link address of P and the execution address of P.
|
||||
// Indirect(expr) represents the result of calling expr as a function.
|
||||
// The result is the return value from the function that is returned in r0.
|
||||
// [msb:lsb] is a bit-mask operation representing the selection of bits in a value
|
||||
enum elf_RTYPE_aarch64
|
||||
{
|
||||
R_AARCH64_NONE = 0x100,
|
||||
|
||||
// ILP32 relocations
|
||||
R_AARCH64_P32_ABS32 = 1,/* Direct 32 bit. */
|
||||
R_AARCH64_P32_COPY = 180,/* Copy symbol at runtime. */
|
||||
R_AARCH64_P32_GLOB_DAT = 181,/* Create GOT entry. */
|
||||
R_AARCH64_P32_JUMP_SLOT = 182,/* Create PLT entry. */
|
||||
R_AARCH64_P32_RELATIVE = 183,/* Adjust by program base. */
|
||||
R_AARCH64_P32_TLS_DTPMOD = 184,/* Module number, 32 bit. */
|
||||
R_AARCH64_P32_TLS_DTPREL = 185,/* Module-relative offset, 32 bit. */
|
||||
R_AARCH64_P32_TLS_TPREL = 186,/* TP-relative offset, 32 bit. */
|
||||
R_AARCH64_P32_TLSDESC = 187,/* TLS Descriptor. */
|
||||
R_AARCH64_P32_IRELATIVE = 188,/* STT_GNU_IFUNC relocation. */
|
||||
|
||||
// 4.6.5 Static Data relocations
|
||||
R_AARCH64_ABS64 = 0x101, // S + A
|
||||
R_AARCH64_ABS32 = 0x102, // S + A
|
||||
R_AARCH64_ABS16 = 0x103,
|
||||
R_AARCH64_PREL64 = 0x104,
|
||||
R_AARCH64_PREL32 = 0x105,
|
||||
R_AARCH64_PREL16 = 0x106,
|
||||
|
||||
// 4.6.6 Static AArch64 relocations
|
||||
R_AARCH64_MOVW_UABS_G0 = 0x107,
|
||||
R_AARCH64_MOVW_UABS_G0_NC = 0x108,
|
||||
R_AARCH64_MOVW_UABS_G1 = 0x109,
|
||||
R_AARCH64_MOVW_UABS_G1_NC = 0x10a,
|
||||
R_AARCH64_MOVW_UABS_G2 = 0x10b,
|
||||
R_AARCH64_MOVW_UABS_G2_NC = 0x10c,
|
||||
R_AARCH64_MOVW_UABS_G3 = 0x10d,
|
||||
R_AARCH64_MOVW_SABS_G0 = 0x10e,
|
||||
R_AARCH64_MOVW_SABS_G1 = 0x10f,
|
||||
R_AARCH64_MOVW_SABS_G2 = 0x110,
|
||||
|
||||
R_AARCH64_LD_PREL_LO19 = 0x111,
|
||||
R_AARCH64_ADR_PREL_LO21 = 0x112,
|
||||
R_AARCH64_ADR_PREL_PG_HI21 = 0x113, // Page(S+A) - Page(P); Set an ADRP immediate value to bits [32:12] of the X
|
||||
R_AARCH64_ADR_PREL_PG_HI21_NC = 0x114,
|
||||
R_AARCH64_ADD_ABS_LO12_NC = 0x115, // S+A; Set an ADD immediate value to bits [11:0] of X
|
||||
R_AARCH64_LDST8_ABS_LO12_NC = 0x116,
|
||||
|
||||
R_AARCH64_TSTBR14 = 0x117,
|
||||
R_AARCH64_CONDBR19 = 0x118,
|
||||
R_AARCH64_JUMP26 = 0x11a, // S+A-P; Set a B immediate field to bits [27:2] of X
|
||||
R_AARCH64_CALL26 = 0x11b, // S+A-P; Set a CALL immediate field to bits [27:2] of X
|
||||
|
||||
R_AARCH64_LDST16_ABS_LO12_NC = 0x11c,
|
||||
R_AARCH64_LDST32_ABS_LO12_NC = 0x11d,
|
||||
R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, // S+A; Set the LD/ST immediate value to bits [11:3] of X
|
||||
|
||||
R_AARCH64_MOVW_PREL_G0 = 0x11f,
|
||||
R_AARCH64_MOVW_PREL_G0_NC = 0x120,
|
||||
R_AARCH64_MOVW_PREL_G1 = 0x121,
|
||||
R_AARCH64_MOVW_PREL_G1_NC = 0x122,
|
||||
R_AARCH64_MOVW_PREL_G2 = 0x123,
|
||||
R_AARCH64_MOVW_PREL_G2_NC = 0x124,
|
||||
R_AARCH64_MOVW_PREL_G3 = 0x125,
|
||||
|
||||
R_AARCH64_LDST128_ABS_LO12_NC = 0x12b,
|
||||
|
||||
R_AARCH64_MOVW_GOTOFF_G0 = 0x12c,
|
||||
R_AARCH64_MOVW_GOTOFF_G0_NC = 0x12d,
|
||||
R_AARCH64_MOVW_GOTOFF_G1 = 0x12e,
|
||||
R_AARCH64_MOVW_GOTOFF_G1_NC = 0x12f,
|
||||
R_AARCH64_MOVW_GOTOFF_G2 = 0x130,
|
||||
R_AARCH64_MOVW_GOTOFF_G2_NC = 0x131,
|
||||
R_AARCH64_MOVW_GOTOFF_G3 = 0x132,
|
||||
|
||||
R_AARCH64_GOTREL64 = 0x133,
|
||||
R_AARCH64_GOTREL32 = 0x134,
|
||||
|
||||
R_AARCH64_GOT_LD_PREL19 = 0x135,
|
||||
R_AARCH64_LD64_GOTOFF_LO15 = 0x136,
|
||||
R_AARCH64_ADR_GOT_PAGE = 0x137, // Page(G(GDAT(S+A)))-Page(P); Set the immediate value of an ADRP to bits [32:12] of X
|
||||
R_AARCH64_LD64_GOT_LO12_NC = 0x138, // G(GDAT(S+A)); Set the LD/ST immediate field to bits [11:3] of X
|
||||
R_AARCH64_LD64_GOTPAGE_LO15 = 0x139,
|
||||
|
||||
R_AARCH64_TLSGD_ADR_PREL21 = 0x200,
|
||||
R_AARCH64_TLSGD_ADR_PAGE21 = 0x201,
|
||||
R_AARCH64_TLSGD_ADD_LO12_NC = 0x202,
|
||||
R_AARCH64_TLSGD_MOVW_G1 = 0x203,
|
||||
R_AARCH64_TLSGD_MOVW_G0_NC = 0x204,
|
||||
|
||||
R_AARCH64_TLSLD_ADR_PREL21 = 0x205,
|
||||
R_AARCH64_TLSLD_ADR_PAGE21 = 0x206,
|
||||
R_AARCH64_TLSLD_ADD_LO12_NC = 0x207,
|
||||
R_AARCH64_TLSLD_MOVW_G1 = 0x208,
|
||||
R_AARCH64_TLSLD_MOVW_G0_NC = 0x209,
|
||||
R_AARCH64_TLSLD_LD_PREL19 = 0x20a,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f,
|
||||
R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210,
|
||||
R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211,
|
||||
R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212,
|
||||
R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213,
|
||||
R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214,
|
||||
R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215,
|
||||
R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216,
|
||||
R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217,
|
||||
R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218,
|
||||
R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219,
|
||||
R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a,
|
||||
|
||||
R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b,
|
||||
R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c,
|
||||
R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d,
|
||||
R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e,
|
||||
R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f,
|
||||
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227,
|
||||
R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228,
|
||||
R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229,
|
||||
R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a,
|
||||
R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b,
|
||||
R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c,
|
||||
R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d,
|
||||
R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e,
|
||||
R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f,
|
||||
|
||||
R_AARCH64_TLSDESC_LD_PREL19 = 0x230,
|
||||
R_AARCH64_TLSDESC_ADR_PREL21 = 0x231,
|
||||
R_AARCH64_TLSDESC_ADR_PAGE21 = 0x232, // R_AARCH64_TLSDESC_ADR_PAGE
|
||||
R_AARCH64_TLSDESC_LD64_LO12 = 0x233, // R_AARCH64_TLSDESC_LD64_LO12_NC
|
||||
R_AARCH64_TLSDESC_ADD_LO12 = 0x234, // R_AARCH64_TLSDESC_ADD_LO12_NC
|
||||
R_AARCH64_TLSDESC_OFF_G1 = 0x235,
|
||||
R_AARCH64_TLSDESC_OFF_G0_NC = 0x236,
|
||||
R_AARCH64_TLSDESC_LDR = 0x237,
|
||||
R_AARCH64_TLSDESC_ADD = 0x238,
|
||||
R_AARCH64_TLSDESC_CALL = 0x239,
|
||||
|
||||
R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 0x23a,
|
||||
R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 0x23b,
|
||||
|
||||
R_AARCH64_TLSLD_LDST128_DTPREL_Lo12 = 0x23c,
|
||||
R_AARCH64_TLSLD_LDST128_DTPREL_Lo12_NC= 0x23d,
|
||||
|
||||
// 4.6.11 Dynamic relocations
|
||||
R_AARCH64_COPY = 0x400,
|
||||
R_AARCH64_GLOB_DAT = 0x401,
|
||||
R_AARCH64_JUMP_SLOT = 0x402,
|
||||
R_AARCH64_RELATIVE = 0x403,
|
||||
R_AARCH64_TLS_DTPREL64 = 0x404,
|
||||
R_AARCH64_TLS_DTPMOD64 = 0x405,
|
||||
R_AARCH64_TLS_TPREL64 = 0x406,
|
||||
R_AARCH64_TLSDESC = 0x407,
|
||||
R_AARCH64_IRELATIVE = 0x408,
|
||||
};
|
||||
|
||||
// Flags:
|
||||
#define EF_ARM_RELEXEC 0x00000001 // dynamic only how to relocation
|
||||
#define EF_ARM_HASENTRY 0x00000002 // e_entry is real start address
|
||||
|
||||
// GNU flags (EABI version = 0)
|
||||
#define EF_ARM_INTERWORK 0x00000004 // interworking enabled
|
||||
#define EF_ARM_APCS_26 0x00000008 // APCS-26 used (otherwise APCS-32)
|
||||
#define EF_ARM_APCS_FLOAT 0x00000010 // floats passed in float registers
|
||||
#define EF_ARM_PIC 0x00000020 // Position-independent code
|
||||
#define EF_ARM_ALIGN8 0x00000040 // 8-bit struct alignment
|
||||
#define EF_ARM_NEW_ABI 0x00000080 // New ABI
|
||||
#define EF_ARM_OLD_ABI 0x00000100 // Old ABI
|
||||
#define EF_ARM_SOFT_FLOAT 0x00000200 // software FP
|
||||
#define EF_ARM_VFP_FLOAT 0x00000400 // VFP float format
|
||||
#define EF_ARM_MAVERICK_FLOAT 0x00000800 // Maverick float format
|
||||
|
||||
// ARM flags:
|
||||
#define EF_ARM_SYMSARESORTED 0x00000004 // Each subsection of the symbol table is sorted by symbol value (NB conflicts with EF_INTERWORK)
|
||||
#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 // Symbols in dynamic symbol tables that are defined in sections
|
||||
// included in program segment n have st_shndx = n + 1. (NB conflicts with EF_APCS26)
|
||||
#define EF_ARM_MAPSYMSFIRST 0x00000010 // Mapping symbols precede other local symbols in the symbol
|
||||
// table (NB conflicts with EF_APCS_FLOAT)
|
||||
#define EF_ARM_LE8 0x00400000 // LE-8 code
|
||||
#define EF_ARM_BE8 0x00800000 // BE-8 code for ARMv6 or later
|
||||
#define EF_ARM_EABIMASK 0xFF000000 // ARM EABI version
|
||||
|
||||
/* Additional symbol types for Thumb. */
|
||||
#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */
|
||||
#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */
|
||||
|
||||
// patching GOT loading,
|
||||
// discard auxiliary values in plt/got
|
||||
// can present offset bypass segment
|
||||
#define ELF_RPL_ARM_DEFAULT (ELF_RPL_GL | ELF_DIS_OFFW | ELF_DIS_GPLT)
|
||||
|
||||
enum elf_SHT_ARM
|
||||
{
|
||||
SHT_ARM_EXIDX = 0x70000001, // Exception Index table
|
||||
SHT_ARM_PREEMPTMAP = 0x70000002, // BPABI DLL dynamic linking pre-emption map
|
||||
SHT_ARM_ATTRIBUTES = 0x70000003, // Object file compatibility attributes
|
||||
SHT_ARM_DEBUGOVERLAY = 0x70000004, //
|
||||
SHT_ARM_OVERLAYSECTION = 0x70000005, //
|
||||
};
|
||||
|
||||
enum elf_PT_ARM
|
||||
{
|
||||
// From binutils-2.27/elfcpp/elfcpp.h
|
||||
PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility information
|
||||
PT_ARM_EXIDX = 0x70000001, // Exception unwind tables
|
||||
};
|
||||
|
||||
enum elf_PT_AARCH64
|
||||
{
|
||||
// From binutils-2.27/elfcpp/elfcpp.h
|
||||
PT_AARCH64_ARCHEXT = 0x70000000, // Platform architecture compatibility information
|
||||
PT_AARCH64_UNWIND = 0x70000001, // Exception unwind tables
|
||||
};
|
||||
|
||||
enum eabi_tags_t
|
||||
{
|
||||
Tag_NULL,
|
||||
Tag_File, // (=1) <uint32: byte-size> <attribute>*
|
||||
Tag_Section, // (=2) <uint32: byte-size> <section number>* 0 <attribute>*
|
||||
Tag_Symbol, // (=3) <unit32: byte-size> <symbol number>* 0 <attribute>*
|
||||
Tag_CPU_raw_name, // (=4), NTBS
|
||||
Tag_CPU_name, // (=5), NTBS
|
||||
Tag_CPU_arch, // (=6), uleb128
|
||||
Tag_CPU_arch_profile, // (=7), uleb128
|
||||
Tag_ARM_ISA_use, // (=8), uleb128
|
||||
Tag_THUMB_ISA_use, // (=9), uleb128
|
||||
Tag_FP_arch, // (=10), uleb128 (formerly Tag_VFP_arch = 10)
|
||||
Tag_VFP_arch = Tag_FP_arch,
|
||||
Tag_WMMX_arch, // (=11), uleb128
|
||||
Tag_NEON_arch, // (=12), uleb128
|
||||
Tag_PCS_config, // (=13), uleb128
|
||||
Tag_ABI_PCS_R9_use, // (=14), uleb128
|
||||
Tag_ABI_PCS_RW_data, // (=15), uleb128
|
||||
Tag_ABI_PCS_RO_data, // (=16), uleb128
|
||||
Tag_ABI_PCS_GOT_use, // (=17), uleb128
|
||||
Tag_ABI_PCS_wchar_t, // (=18), uleb128
|
||||
Tag_ABI_FP_rounding, // (=19), uleb128
|
||||
Tag_ABI_FP_denormal, // (=20), uleb128
|
||||
Tag_ABI_FP_exceptions, // (=21), uleb128
|
||||
Tag_ABI_FP_user_exceptions, // (=22), uleb128
|
||||
Tag_ABI_FP_number_model, // (=23), uleb128
|
||||
Tag_ABI_align_needed, // (=24), uleb128
|
||||
Tag_ABI_align8_needed = Tag_ABI_align_needed,
|
||||
Tag_ABI_align_preserved, // (=25), uleb128
|
||||
Tag_ABI_align8_preserved = Tag_ABI_align_preserved,
|
||||
Tag_ABI_enum_size, // (=26), uleb128
|
||||
Tag_ABI_HardFP_use, // (=27), uleb128
|
||||
Tag_ABI_VFP_args, // (=28), uleb128
|
||||
Tag_ABI_WMMX_args, // (=29), uleb128
|
||||
Tag_ABI_optimization_goals, // (=30), uleb128
|
||||
Tag_ABI_FP_optimization_goals, // (=31), uleb128
|
||||
Tag_compatibility, // (=32), uleb128: flag, NTBS: vendor-name
|
||||
Tag_CPU_unaligned_access=34, // (=34), uleb128
|
||||
Tag_FP_HP_extension=36, // (=36), uleb128 (formerly Tag_VFP_HP_extension = 36)
|
||||
Tag_VFP_HP_extension = Tag_FP_HP_extension,
|
||||
Tag_ABI_FP_16bit_format=38, // (=38), uleb128
|
||||
Tag_MPextension_use=42, // (=42), uleb128
|
||||
Tag_DIV_use=44, // (=44), uleb128
|
||||
Tag_nodefaults=64, // (=64), uleb128: ignored (write as 0)
|
||||
Tag_also_compatible_with, // (=65), NTBS: data; ULEB128-encoded tag followed by a value of that tag.
|
||||
Tag_T2EE_use, // (=66), uleb128
|
||||
Tag_conformance, // (=67), string: ABI-version
|
||||
Tag_Virtualization_use, // (=68), uleb128
|
||||
Tag_MPextension_use_legacy=70, // (=70),
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class arm_arch_specific_t : public arch_specific_t
|
||||
{
|
||||
public:
|
||||
enum isa_t
|
||||
{
|
||||
isa_arm = 1,
|
||||
isa_thumb
|
||||
};
|
||||
typedef void isa_handler_t(
|
||||
reader_t &reader,
|
||||
sym_rel &symbol,
|
||||
isa_t isa,
|
||||
bool force);
|
||||
private:
|
||||
typedef std::map<uint64, isa_t> section_isa_ranges_t;
|
||||
typedef std::map<elf_shndx_t, section_isa_ranges_t> isa_ranges_t;
|
||||
|
||||
isa_ranges_t isa_ranges;
|
||||
std::set<ea_t> forced_isas;
|
||||
|
||||
isa_handler_t *isa_handler = nullptr;
|
||||
ea_t debug_segbase = 0;
|
||||
bool has_mapsym = false;
|
||||
bool track_mapsym = false;
|
||||
bool be8_code = false;
|
||||
|
||||
void notify_isa(reader_t &reader, sym_rel &symbol, isa_t isa, bool force)
|
||||
{
|
||||
if ( isa_handler != NULL )
|
||||
isa_handler(reader, symbol, isa, force);
|
||||
}
|
||||
|
||||
isa_t get_isa(const sym_rel &symbol) const;
|
||||
void set_isa(const sym_rel &symbol, isa_t isa);
|
||||
|
||||
friend void arm_isa_handler(
|
||||
reader_t &reader,
|
||||
sym_rel &symbol,
|
||||
arm_arch_specific_t::isa_t isa,
|
||||
bool force);
|
||||
|
||||
public:
|
||||
virtual ~arm_arch_specific_t() {}
|
||||
virtual void on_start_symbols(reader_t &reader) override;
|
||||
virtual void on_symbol_read(reader_t &reader, sym_rel &sym) override;
|
||||
bool is_mapping_symbol(const char *name) const;
|
||||
bool has_mapping_symbols() const { return has_mapsym; }
|
||||
|
||||
// Tracking mapping symbols can be useful for
|
||||
// determining whether a certain function is using
|
||||
// the Thumb or ARM ISA.
|
||||
// In some ELF files, the only way to know what ISA
|
||||
// certain functions are in is by looking at some
|
||||
// mapping symbols (i.e., '$a', '$t').
|
||||
// By default, tracking of such symbols in an
|
||||
// instance of this class is _not_ enabled.
|
||||
void set_mapping_symbols_tracking(bool track) { track_mapsym = track; }
|
||||
bool is_mapping_symbols_tracking() const { return track_mapsym; }
|
||||
|
||||
void set_isa_handler(isa_handler_t *ih, ea_t dea)
|
||||
{
|
||||
isa_handler = ih;
|
||||
debug_segbase = dea;
|
||||
}
|
||||
|
||||
void set_be8(bool be8) { be8_code = be8; }
|
||||
bool is_be8() { return be8_code; }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Specific flags that will be set on sym_rel instances.
|
||||
enum arm_sym_rel_flags
|
||||
{
|
||||
thumb_function = 1
|
||||
};
|
||||
|
||||
#endif
|
||||
87
idasdk76/ldr/elf/elfr_avr.h
Normal file
87
idasdk76/ldr/elf/elfr_avr.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#ifndef __ELFR_AVR_H__
|
||||
#define __ELFR_AVR_H__
|
||||
|
||||
#ifndef __ELFBASE_H__
|
||||
#include "elfbase.h"
|
||||
#endif
|
||||
|
||||
enum elf_RTYPE_avr
|
||||
{
|
||||
R_AVR_NONE = 0,
|
||||
R_AVR_32 = 1,
|
||||
R_AVR_7_PCREL = 2,
|
||||
R_AVR_13_PCREL = 3,
|
||||
R_AVR_16 = 4,
|
||||
R_AVR_16PM = 5,
|
||||
R_AVR_LO8_LDI = 6,
|
||||
R_AVR_HI8_LDI = 7,
|
||||
R_AVR_HH8_LDI = 8,
|
||||
R_AVR_LO8_LDI_NEG = 9,
|
||||
R_AVR_HI8_LDI_NEG = 10,
|
||||
R_AVR_HH8_LDI_NEG = 11,
|
||||
R_AVR_LO8_LDI_PM = 12,
|
||||
R_AVR_HI8_LDI_PM = 13,
|
||||
R_AVR_HH8_LDI_PM = 14,
|
||||
R_AVR_LO8_LDI_PM_NEG = 15,
|
||||
R_AVR_HI8_LDI_PM_NEG = 16,
|
||||
R_AVR_HH8_LDI_PM_NEG = 17,
|
||||
R_AVR_CALL = 18,
|
||||
// *nix obj's specific
|
||||
R_AVR_LDI = 19,
|
||||
R_AVR_6 = 20,
|
||||
R_AVR_6_ADIW = 21,
|
||||
R_AVR_MS8_LDI = 22,
|
||||
R_AVR_MS8_LDI_NEG = 23,
|
||||
R_AVR_LO8_LDI_GS = 24,
|
||||
R_AVR_HI8_LDI_GS = 25,
|
||||
R_AVR_8 = 26,
|
||||
R_AVR_8_LO8 = 27,
|
||||
R_AVR_8_HI8 = 28,
|
||||
R_AVR_8_HLO8 = 29,
|
||||
R_AVR_DIFF8 = 30,
|
||||
R_AVR_DIFF16 = 31,
|
||||
R_AVR_DIFF32 = 32,
|
||||
R_AVR_LDS_STS_16 = 33,
|
||||
R_AVR_PORT6 = 34,
|
||||
R_AVR_PORT5 = 35,
|
||||
R_AVR_32_PCREL = 36,
|
||||
};
|
||||
|
||||
// Flags:
|
||||
// If bit #7 is set, it is assumed that the elf file uses local symbols
|
||||
// as reference for the relocations so that linker relaxation is possible.
|
||||
#define EF_AVR_LINKRELAX_PREPARED 0x80
|
||||
|
||||
// Processor specific flags for the ELF header e_flags field.
|
||||
#define EF_AVR_MACH 0x7F
|
||||
#define E_AVR_MACH_AVR1 1
|
||||
#define E_AVR_MACH_AVR2 2
|
||||
#define E_AVR_MACH_AVR25 25
|
||||
#define E_AVR_MACH_AVR3 3
|
||||
#define E_AVR_MACH_AVR31 31
|
||||
#define E_AVR_MACH_AVR35 35
|
||||
#define E_AVR_MACH_AVR4 4
|
||||
#define E_AVR_MACH_AVR5 5
|
||||
#define E_AVR_MACH_AVR51 51
|
||||
#define E_AVR_MACH_AVR6 6
|
||||
#define E_AVR_MACH_TINY 100
|
||||
#define E_AVR_MACH_XMEGA1 101
|
||||
#define E_AVR_MACH_XMEGA2 102
|
||||
#define E_AVR_MACH_XMEGA3 103
|
||||
#define E_AVR_MACH_XMEGA4 104
|
||||
#define E_AVR_MACH_XMEGA5 105
|
||||
#define E_AVR_MACH_XMEGA6 106
|
||||
#define E_AVR_MACH_XMEGA7 107
|
||||
|
||||
// netnode flag's and constant
|
||||
#define AVR_INFO_NODENAME "$ atmel"
|
||||
#define ELF_AVR_TAG 'f'
|
||||
#define ELF_AVR_LDI_NEG 1
|
||||
#define ELF_AVR_RAM_OFF 2
|
||||
#define ELF_AVR_EEP_OFF 3
|
||||
#define ELF_AVR_ABS_OFF 4
|
||||
#define ELF_AVR_RAMBASE 0x800000
|
||||
#define ELF_AVR_EEPROMBASE 0x810000
|
||||
#define ELF_AVR_ABSBASE 0x1000000
|
||||
|
||||
#endif
|
||||
272
idasdk76/ldr/elf/elfr_ia64.h
Normal file
272
idasdk76/ldr/elf/elfr_ia64.h
Normal file
@@ -0,0 +1,272 @@
|
||||
#ifndef __ELFR_IA64_H__
|
||||
#define __ELFR_IA64_H__
|
||||
|
||||
#ifndef __ELFBASE_H__
|
||||
#include "elfbase.h"
|
||||
#endif
|
||||
|
||||
/* Bits in the e_flags field of the Elf64_Ehdr: */
|
||||
#define EF_IA_64_MASKOS 0x00ff000f /* os-specific flags */
|
||||
#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
|
||||
#define EFA_IA_64 0x00000000
|
||||
/* ??? These four definitions are not part of the SVR4 ABI.
|
||||
They were present in David's initial code drop, so it is probable
|
||||
that they are used by HP/UX. */
|
||||
#define EF_IA_64_TRAPNIL (1 << 0) /* Trap NIL pointer dereferences. */
|
||||
#define EF_IA_64_LAZYSWAP (1 << 1) /* Lazy Swap algorithm */
|
||||
#define EF_IA_64_EXT (1 << 2) /* Program uses arch. extensions. */
|
||||
#define EF_IA_64_BE (1 << 3) /* PSR BE bit set (big-endian). */
|
||||
#define EFA_IA_64_EAS2_3 0x23000000 /* IA64 EAS 2.3. */
|
||||
|
||||
#define EF_IA_64_ABI64 (1 << 4) /* 64-bit ABI. */
|
||||
/* Not used yet. */
|
||||
#define EF_IA_64_REDUCEDFP (1 << 5) /* Only FP6-FP11 used. */
|
||||
#define EF_IA_64_CONS_GP (1 << 6) /* gp as program wide constant. */
|
||||
#define EF_IA_64_NOFUNCDESC_CONS_GP (1 << 7) /* And no function descriptors. */
|
||||
/* Not used yet. */
|
||||
#define EF_IA_64_ABSOLUTE (1 << 8) /* Load at absolute addresses. */
|
||||
|
||||
/*============================================================================
|
||||
The R_EM_* macros are the IA_64 relocation types
|
||||
============================================================================*/
|
||||
/*
|
||||
** These are "real" Tahoe relocations. The offset in a relocation
|
||||
** applied to a data location is the actual byte address of the
|
||||
** 32-/64-bit field to relocate. The value of (offset & ~3) in
|
||||
** an instruction relocation is the byte offset of the bundle
|
||||
** the instruction lives in; the value of (offset & 3) signifies:
|
||||
** 0: first instruction slot in bundle
|
||||
** 1: second instruction slot in bundle
|
||||
** 2: third instruction slot in bundle
|
||||
**
|
||||
** Little piece of info: the first (hex) digit specifies the
|
||||
** expression type, while the second specifies the format of
|
||||
** the data word being relocated.
|
||||
*/
|
||||
|
||||
// relocation field - word32 with HIGH BYTE FIRST!!!
|
||||
// A- from Elf32_Rela
|
||||
// B- Loading address of shared object
|
||||
// G- offset into global objet table
|
||||
// GOT- adress of global object table
|
||||
// L- linkage table entry
|
||||
// P- plase of storage unit (computed using r_offset)
|
||||
// S- value of symbol
|
||||
enum elf_RTYPE_ia64
|
||||
{
|
||||
R_IA64_NONE = 0x00, /* none */
|
||||
|
||||
R_IA64_IMM14 = 0x21, /* symbol + addend, add imm14 */
|
||||
R_IA64_IMM22 = 0x22, /* symbol + addend, add imm22 */
|
||||
R_IA64_IMM64 = 0x23, /* symbol + addend, mov imm64 */
|
||||
R_IA64_DIR32MSB = 0x24, /* symbol + addend, data4 MSB */
|
||||
R_IA64_DIR32LSB = 0x25, /* symbol + addend, data4 LSB */
|
||||
R_IA64_DIR64MSB = 0x26, /* symbol + addend, data8 MSB */
|
||||
R_IA64_DIR64LSB = 0x27, /* symbol + addend, data8 LSB */
|
||||
|
||||
R_IA64_GPREL22 = 0x2a, /* @gprel(sym + add), add imm22 */
|
||||
R_IA64_GPREL64I = 0x2b, /* @gprel(sym + add), mov imm64 */
|
||||
R_IA64_GPREL32MSB = 0x2c, /* @gprel(sym + add), data4 MSB ## */
|
||||
R_IA64_GPREL32LSB = 0x2d, /* @gprel(sym + add), data4 LSB ## */
|
||||
R_IA64_GPREL64MSB = 0x2e, /* @gprel(sym + add), data8 MSB */
|
||||
R_IA64_GPREL64LSB = 0x2f, /* @gprel(sym + add), data8 LSB */
|
||||
|
||||
R_IA64_LTOFF22 = 0x32, /* @ltoff(sym + add), add imm22 */
|
||||
R_IA64_LTOFF64I = 0x33, /* @ltoff(sym + add), mov imm64 */
|
||||
|
||||
R_IA64_PLTOFF22 = 0x3a, /* @pltoff(sym + add), add imm22 */
|
||||
R_IA64_PLTOFF64I = 0x3b, /* @pltoff(sym + add), mov imm64 */
|
||||
R_IA64_PLTOFF64MSB = 0x3e, /* @pltoff(sym + add), data8 MSB */
|
||||
R_IA64_PLTOFF64LSB = 0x3f, /* @pltoff(sym + add), data8 LSB */
|
||||
|
||||
R_IA64_FPTR64I = 0x43, /* @fptr(sym + add), mov imm64 */
|
||||
R_IA64_FPTR32MSB = 0x44, /* @fptr(sym + add), data4 MSB */
|
||||
R_IA64_FPTR32LSB = 0x45, /* @fptr(sym + add), data4 LSB */
|
||||
R_IA64_FPTR64MSB = 0x46, /* @fptr(sym + add), data8 MSB */
|
||||
R_IA64_FPTR64LSB = 0x47, /* @fptr(sym + add), data8 LSB */
|
||||
|
||||
R_IA64_PCREL60B = 0x48, /* @pcrel(sym + add), brl */
|
||||
R_IA64_PCREL21B = 0x49, /* @pcrel(sym + add), ptb, call */
|
||||
R_IA64_PCREL21M = 0x4a, /* @pcrel(sym + add), chk.s */
|
||||
R_IA64_PCREL21F = 0x4b, /* @pcrel(sym + add), fchkf */
|
||||
R_IA64_PCREL32MSB = 0x4c, /* @pcrel(sym + add), data4 MSB */
|
||||
R_IA64_PCREL32LSB = 0x4d, /* @pcrel(sym + add), data4 LSB */
|
||||
R_IA64_PCREL64MSB = 0x4e, /* @pcrel(sym + add), data8 MSB */
|
||||
R_IA64_PCREL64LSB = 0x4f, /* @pcrel(sym + add), data8 LSB */
|
||||
|
||||
R_IA64_LTOFF_FPTR22 = 0x52, /* @ltoff(@fptr(s+a)), imm22 */
|
||||
R_IA64_LTOFF_FPTR64I = 0x53, /* @ltoff(@fptr(s+a)), imm64 */
|
||||
R_IA64_LTOFF_FPTR32MSB = 0x54, /* @ltoff(@fptr(s+a)), 4 MSB */
|
||||
R_IA64_LTOFF_FPTR32LSB = 0x55, /* @ltoff(@fptr(s+a)), 4 LSB */
|
||||
R_IA64_LTOFF_FPTR64MSB = 0x56, /* @ltoff(@fptr(s+a)), 8 MSB ##*/
|
||||
R_IA64_LTOFF_FPTR64LSB = 0x57, /* @ltoff(@fptr(s+a)), 8 LSB ##*/
|
||||
|
||||
R_IA64_SEGBASE = 0x58, /* set segment base for @segrel ## */
|
||||
R_IA64_SEGREL32MSB = 0x5c, /* @segrel(sym + add), data4 MSB */
|
||||
R_IA64_SEGREL32LSB = 0x5d, /* @segrel(sym + add), data4 LSB */
|
||||
R_IA64_SEGREL64MSB = 0x5e, /* @segrel(sym + add), data8 MSB */
|
||||
R_IA64_SEGREL64LSB = 0x5f, /* @segrel(sym + add), data8 LSB */
|
||||
|
||||
R_IA64_SECREL32MSB = 0x64, /* @secrel(sym + add), data4 MSB */
|
||||
R_IA64_SECREL32LSB = 0x65, /* @secrel(sym + add), data4 LSB */
|
||||
R_IA64_SECREL64MSB = 0x66, /* @secrel(sym + add), data8 MSB */
|
||||
R_IA64_SECREL64LSB = 0x67, /* @secrel(sym + add), data8 LSB */
|
||||
|
||||
R_IA64_REL32MSB = 0x6c, /* data 4 + REL */
|
||||
R_IA64_REL32LSB = 0x6d, /* data 4 + REL */
|
||||
R_IA64_REL64MSB = 0x6e, /* data 8 + REL */
|
||||
R_IA64_REL64LSB = 0x6f, /* data 8 + REL */
|
||||
|
||||
R_IA64_LTV32MSB = 0x74, /* symbol + addend, data4 MSB */
|
||||
R_IA64_LTV32LSB = 0x75, /* symbol + addend, data4 LSB */
|
||||
R_IA64_LTV64MSB = 0x76, /* symbol + addend, data8 MSB */
|
||||
R_IA64_LTV64LSB = 0x77, /* symbol + addend, data8 LSB */
|
||||
|
||||
R_IA64_PCREL21BI = 0x79, /* @pcrel(sym + add), ptb, call */
|
||||
R_IA64_PCREL22 = 0x7a, /* @pcrel(sym + add), imm22 */
|
||||
R_IA64_PCREL64I = 0x7b, /* @pcrel(sym + add), imm64 */
|
||||
|
||||
R_IA64_IPLTMSB = 0x80, /* dynamic reloc, imported PLT, MSB */
|
||||
R_IA64_IPLTLSB = 0x81, /* dynamic reloc, imported PLT, LSB */
|
||||
R_IA64_EPLTMSB = 0x82, /* dynamic reloc, exported PLT, ## */
|
||||
R_IA64_EPLTLSB = 0x83, /* dynamic reloc, exported PLT, ## */
|
||||
R_IA64_COPY = 0x84, /* dynamic reloc, data copy ## */
|
||||
R_IA64_SUB = 0x85, /* Addend and symbol difference */
|
||||
R_IA64_LTOFF22X = 0x86, /* LTOFF22, relaxable. */
|
||||
R_IA64_LDXMOV = 0x87, /* Use of LTOFF22X. */
|
||||
|
||||
R_IA64_TPREL14 = 0x91, /* @tprel(sym+add), add imm14 */
|
||||
R_IA64_TPREL22 = 0x92, /* sym-TP+add, add imm22 ## */
|
||||
R_IA64_TPREL64I = 0x93, /* @tprel(sym+add), add imm64 */
|
||||
R_IA64_TPREL64MSB = 0x96, /* sym-TP+add, data8 MSB ## */
|
||||
R_IA64_TPREL64LSB = 0x97, /* sym-TP+add, data8 LSB ## */
|
||||
|
||||
R_IA64_LTOFF_TP22 = 0x9a, /* @ltoff(sym-TP+add), add imm22 ## */
|
||||
|
||||
R_IA64_DTPMOD64MSB = 0xa6, /* @dtpmod(sym+add), data8 MSB */
|
||||
R_IA64_DTPMOD64LSB = 0xa7, /* @dtpmod(sym+add), data8 LSB */
|
||||
R_IA64_LTOFF_DTPMOD22 = 0xaa, /* @ltoff(@dtpmod(s+a)), imm22 */
|
||||
|
||||
R_IA64_DTPREL14 = 0xb1, /* @dtprel(sym+add), imm14 */
|
||||
R_IA64_DTPREL22 = 0xb2, /* @dtprel(sym+add), imm22 */
|
||||
R_IA64_DTPREL64I = 0xb3, /* @dtprel(sym+add), imm64 */
|
||||
R_IA64_DTPREL32MSB = 0xb4, /* @dtprel(sym+add), data4 MSB */
|
||||
R_IA64_DTPREL32LSB = 0xb5, /* @dtprel(sym+add), data4 LSB */
|
||||
R_IA64_DTPREL64MSB = 0xb6, /* @dtprel(sym+add), data8 MSB */
|
||||
R_IA64_DTPREL64LSB = 0xb7, /* @dtprel(sym+add), data8 LSB */
|
||||
|
||||
R_IA64_LTOFF_DTPREL22 = 0xba, /* @ltoff(@dtprel(s+a)), imm22 */
|
||||
|
||||
R_IA64_MAX_RELOC_CODE = 0xba
|
||||
|
||||
};
|
||||
|
||||
// convert plt PIC => noPIC,
|
||||
// patching GOT loading,
|
||||
// discard auxiliary values in plt/got
|
||||
#define ELF_RPL_IA64_DEFAULT (ELF_RPL_PLP | ELF_RPL_GL)
|
||||
|
||||
|
||||
enum elf_SHT_IA64
|
||||
{
|
||||
SHT_IA_64_EXT = 0x70000000, /* extension bits */
|
||||
SHT_IA_64_UNWIND = 0x70000001, /* unwind bits */
|
||||
};
|
||||
|
||||
/*============================================================================
|
||||
The PT_* macros are the values of p_type in ElfXX_Phdr.
|
||||
============================================================================*/
|
||||
enum elf_PT_IA64
|
||||
{
|
||||
|
||||
PT_HP_TLS = (PT_LOOS + 0x0), /* TLS */
|
||||
PT_HP_CORE_NONE = (PT_LOOS + 0x1), /* core file information */
|
||||
PT_HP_CORE_VERSION = (PT_LOOS + 0x2),
|
||||
PT_HP_CORE_KERNEL = (PT_LOOS + 0x3),
|
||||
PT_HP_CORE_COMM = (PT_LOOS + 0x4),
|
||||
PT_HP_CORE_PROC = (PT_LOOS + 0x5),
|
||||
PT_HP_CORE_LOADABLE = (PT_LOOS + 0x6),
|
||||
PT_HP_CORE_STACK = (PT_LOOS + 0x7),
|
||||
PT_HP_CORE_SHM = (PT_LOOS + 0x8),
|
||||
PT_HP_CORE_MMF = (PT_LOOS + 0x9),
|
||||
PT_HP_PARALLEL = (PT_LOOS + 0x10), /* parallel information header */
|
||||
PT_HP_FASTBIND = (PT_LOOS + 0x11), /* fastbind data segment */
|
||||
PT_HP_OPT_ANNOT = (PT_LOOS + 0x12), /* dynamic opt. annotations */
|
||||
PT_HP_HSL_ANNOT = (PT_LOOS + 0x13), /* HSL annotations */
|
||||
PT_HP_STACK = (PT_LOOS + 0x14), /* executable stack */
|
||||
PT_HP_CORE_UTSNAME = (PT_LOOS + 0x15), /* Extended utsname() core struct */
|
||||
PT_HP_LINKER_FOOTPRINT = (PT_LOOS + 0x16), /* linker footprint */
|
||||
|
||||
PT_IA_64_ARCHEXT = (PT_LOPROC + 0), /* arch. extension bits */
|
||||
PT_IA_64_UNWIND = (PT_LOPROC + 1), /* IA64 unwind bits */
|
||||
};
|
||||
|
||||
/*============================================================================
|
||||
The PF_* macros are the segment flag bits in p_flags of ElfXX_Phdr.
|
||||
============================================================================*/
|
||||
enum elf_PF_IA64
|
||||
{
|
||||
PF_HP_ENABLE_RECOVER = 0x00020000, /* enable recovery mode */
|
||||
PF_HP_CODE = 0x00040000, /* code hint */
|
||||
PF_HP_MODIFY = 0x00080000, /* modify hint */
|
||||
PF_HP_PAGE_SIZE = 0x00100000, /* use explicit page size */
|
||||
PF_HP_FAR_SHARED = 0x00200000, /* far shared data */
|
||||
PF_HP_NEAR_SHARED = 0x00400000, /* near shared data */
|
||||
PF_HP_LAZYSWAP = 0x00800000, /* lazy swap allocation */
|
||||
PF_IA_64_NORECOV = 0x80000000, /* segment contains code that uses
|
||||
speculative instructions w/o
|
||||
recovery code. */
|
||||
};
|
||||
|
||||
/*============================================================================
|
||||
The NOTE_* macros are the note types for SHT_NOTE sections
|
||||
============================================================================*/
|
||||
|
||||
#define NOTE_HP_COMPILER 1 /* Compiler identification string */
|
||||
#define NOTE_HP_COPYRIGHT 2 /* Copyright string */
|
||||
#define NOTE_HP_VERSION 3 /* Version string */
|
||||
#define NOTE_HP_SRCFILE_INFO 4 /* Source file info for performance tools */
|
||||
#define NOTE_HP_LINKER 5 /* Linker identification string */
|
||||
#define NOTE_HP_INSTRUMENTED 6 /* instrumentation data */
|
||||
#define NOTE_HP_UX_OPTIONS 7 /* elf hdr extension fields */
|
||||
|
||||
/*============================================================================
|
||||
The DT_* defines are the allowed values of d_tag in ElfXX_dyn.
|
||||
These are the Dynamic Array types.
|
||||
============================================================================*/
|
||||
|
||||
/* (i)gnore (m)andatory */
|
||||
/* (o)ptional */
|
||||
/* d_un Exec DLL */
|
||||
/* ---- ---- --- */
|
||||
enum elf_DT_IA64
|
||||
{
|
||||
DT_HP_LOAD_MAP = (DT_LOOS + 0x0), /* d_ptr m - */
|
||||
DT_HP_DLD_FLAGS = (DT_LOOS + 0x1), /* d_val m - */
|
||||
DT_HP_DLD_HOOK = (DT_LOOS + 0x2), /* d_ptr m - */
|
||||
DT_HP_UX10_INIT = (DT_LOOS + 0x3), /* d_ptr o o */
|
||||
DT_HP_UX10_INITSZ = (DT_LOOS + 0x4), /* d_ptr o o */
|
||||
DT_HP_PREINIT = (DT_LOOS + 0x5), /* d_ptr o - */
|
||||
DT_HP_PREINITSZ = (DT_LOOS + 0x6), /* d_ptr o - */
|
||||
DT_HP_NEEDED = (DT_LOOS + 0x7), /* d_val o o */
|
||||
DT_HP_TIME_STAMP = (DT_LOOS + 0x8), /* d_val o o */
|
||||
DT_HP_CHECKSUM = (DT_LOOS + 0x9), /* d_val o o */
|
||||
DT_HP_GST_SIZE = (DT_LOOS + 0xa), /* d_val o - */
|
||||
DT_HP_GST_VERSION = (DT_LOOS + 0xb), /* d_val o o */
|
||||
DT_HP_GST_HASHVAL = (DT_LOOS + 0xc), /* d_ptr o o */
|
||||
DT_HP_EPLTREL = (DT_LOOS + 0xd), /* d_ptr o o */
|
||||
DT_HP_EPLTRELSZ = (DT_LOOS + 0xe), /* d_ptr o o */
|
||||
DT_HP_FILTERED = (DT_LOOS + 0xf), /* d_val - o */
|
||||
DT_HP_FILTER_TLS = (DT_LOOS + 0x10),/* d_val - o */
|
||||
DT_HP_COMPAT_FILTERED = (DT_LOOS + 0x11),/* d_val - o */
|
||||
DT_HP_LAZYLOAD = (DT_LOOS + 0x12),/* d_val o - */
|
||||
DT_HP_BIND_NOW_COUNT = (DT_LOOS + 0x13),/* d_val o o */
|
||||
DT_PLT = (DT_LOOS + 0x14),/* d_ptr o o */
|
||||
DT_PLT_SIZE = (DT_LOOS + 0x15),/* d_val o o */
|
||||
DT_DLT = (DT_LOOS + 0x16),/* d_ptr o o */
|
||||
DT_DLT_SIZE = (DT_LOOS + 0x17),/* d_val o o */
|
||||
DT_HP_SYM_CHECKSUM = (DT_LOOS + 0x18),/* d_val o o */
|
||||
DT_IA_64_PLT_RESERVE = 0x70000000,
|
||||
};
|
||||
|
||||
#endif
|
||||
476
idasdk76/ldr/elf/elfr_mips.h
Normal file
476
idasdk76/ldr/elf/elfr_mips.h
Normal file
@@ -0,0 +1,476 @@
|
||||
#ifndef __ELFR_MIP_H__
|
||||
#define __ELFR_MIP_H__
|
||||
|
||||
#ifndef __ELFBASE_H__
|
||||
#include "elfbase.h"
|
||||
#endif
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
//
|
||||
// e_flags
|
||||
//
|
||||
|
||||
#define EF_MIPS_NOREORDER 0x00000001 // At least one .noreorder directive appears in the source.
|
||||
#define EF_MIPS_PIC 0x00000002 // File contains position independent code.
|
||||
#define EF_MIPS_CPIC 0x00000004 // Code in file uses the standard calling sequence for calling osition independent code.
|
||||
#define EF_MIPS_UGEN_ALLOC 0x00000008
|
||||
#define EF_MIPS_UCODE 0x00000010 // Code in file uses UCODE (obsolete)
|
||||
#define EF_MIPS_ABI2 0x00000020 // Code in file uses new ABI (-n32 on Irix 6).
|
||||
#define EF_MIPS_DYNAMIC 0x00000040 // MIPS dynamic
|
||||
#define EF_MIPS_OPTIONS_FIRST 0x00000080
|
||||
#define EF_MIPS_32BITMODE 0x00000100 // Indicates code compiled for a 64-bit machine in 32-bit mode. (regs are 32-bits wide.)
|
||||
#define EF_MIPS_FP64 0x00000200 // 32-bit machine but FP registers are 64-bit (gcc -mfp64)
|
||||
#define EF_MIPS_NAN2008 0x00000400 // Uses IEE 754-2008 NaN encoding
|
||||
#define EF_MIPS_ARCH 0xF0000000 // Four bit MIPS architecture field.
|
||||
#define E_MIPS_ARCH_1 0x00000000 // -mips1 code.
|
||||
#define E_MIPS_ARCH_2 0x10000000 // -mips2 code.
|
||||
#define E_MIPS_ARCH_3 0x20000000 // -mips3 code.
|
||||
#define E_MIPS_ARCH_4 0x30000000 // -mips4 code.
|
||||
#define E_MIPS_ARCH_5 0x40000000 // -mips5 code.
|
||||
#define E_MIPS_ARCH_32 0x50000000 // -mips32 code.
|
||||
#define E_MIPS_ARCH_64 0x60000000 // -mips64 code.
|
||||
#define E_MIPS_ARCH_32R2 0x70000000 // -mips32r2
|
||||
#define E_MIPS_ARCH_64R2 0x80000000 // -mips64r2
|
||||
#define E_MIPS_ARCH_32R6 0x90000000 // -mips32r6
|
||||
#define E_MIPS_ARCH_64R6 0xA0000000 // -mips64r6
|
||||
#define EF_MIPS_ABI 0x0000F000 // The ABI of the file. Also see EF_MIPS_ABI2 above.
|
||||
#define E_MIPS_ABI_O32 0x00001000 // The original o32 abi.
|
||||
#define E_MIPS_ABI_O64 0x00002000 // O32 extended to work on 64 bit architectures
|
||||
#define E_MIPS_ABI_EABI32 0x00003000 // EABI in 32 bit mode
|
||||
#define E_MIPS_ABI_EABI64 0x00004000 // EABI in 64 bit mode
|
||||
#define EF_MIPS_ARCH_ASE 0x0F000000 // Architectural Extensions used by this file
|
||||
#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 // Use MDMX multimedia extensions
|
||||
#define EF_MIPS_ARCH_ASE_M16 0x04000000 // Use MIPS-16 ISA extensions
|
||||
#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 // Use microMIPS ISA extensions
|
||||
|
||||
/* Machine variant if we know it. This field was invented at Cygnus,
|
||||
but it is hoped that other vendors will adopt it. If some standard
|
||||
is developed, this code should be changed to follow it. */
|
||||
|
||||
#define EF_MIPS_MACH 0x00FF0000
|
||||
|
||||
/* Cygnus is choosing values between 80 and 9F;
|
||||
00 - 7F should be left for a future standard;
|
||||
the rest are open. */
|
||||
|
||||
#define E_MIPS_MACH_3900 0x00810000 // R3900/Toshiba TX39
|
||||
#define E_MIPS_MACH_4010 0x00820000 //
|
||||
#define E_MIPS_MACH_4100 0x00830000
|
||||
#define E_MIPS_MACH_4650 0x00850000
|
||||
#define E_MIPS_MACH_4120 0x00870000
|
||||
#define E_MIPS_MACH_4111 0x00880000
|
||||
#define E_MIPS_MACH_MIPS32_4K 0x00890000
|
||||
#define E_MIPS_MACH_SB1 0x008A0000 // SiByte SB-1
|
||||
#define E_MIPS_MACH_OCTEON 0x008B0000 // Cavium Networks OCTEON
|
||||
#define E_MIPS_MACH_XLR 0x008C0000 // RMI XLR
|
||||
#define E_MIPS_MACH_OCTEON2 0x008D0000 // Cavium Networks OCTEON 2
|
||||
#define E_MIPS_MACH_OCTEON3 0x008E0000 // Cavium Networks OCTEON 3
|
||||
#define E_MIPS_MACH_5400 0x00910000
|
||||
#define E_MIPS_MACH_5900 0x00920000 // r5900 (Sony Playstation 2 Emotion Engine)
|
||||
#define E_MIPS_MACH_5500 0x00980000
|
||||
#define E_MIPS_MACH_9000 0x00990000
|
||||
#define E_MIPS_MACH_LS2E 0x00A00000 // Loongson/Godson 2E
|
||||
#define E_MIPS_MACH_LS2F 0x00A10000 // Loongson/Godson 2F
|
||||
#define E_MIPS_MACH_ALLEGREX 0x00A20000 // Allegrex (Sony PlayStation Portable)
|
||||
#define E_MIPS_MACH_LS3A 0x00A20000 // Loongson/Godson 3A
|
||||
|
||||
//
|
||||
// p_flags
|
||||
//
|
||||
|
||||
#define PF_MIPS_LOCAL 0x10000000 // special p_flags
|
||||
|
||||
// relocation field - word32 with HIGH BYTE FIRST!!!
|
||||
// A- from Elf32_Rela
|
||||
// B- Loading address of shared object
|
||||
// G- offset into global objet table
|
||||
// GOT- adress of global object table
|
||||
// L- linkage table entry
|
||||
// P- plase of storage unit (computed using r_offset)
|
||||
// S- value of symbol
|
||||
enum elf_RTYPE_mips
|
||||
{
|
||||
R_MIPS_NONE = 0, // No reloc
|
||||
R_MIPS_16 = 1,
|
||||
R_MIPS_32 = 2, // S+A-P Direct32
|
||||
R_MIPS_REL = 3, // S+A Relative32
|
||||
R_MIPS_26 = 4, // S+A Relative26
|
||||
R_MIPS_HI16 = 5,
|
||||
R_MIPS_LO16 = 6,
|
||||
R_MIPS_GPREL = 7, // S+A Relative16
|
||||
R_MIPS_LITERAL = 8,
|
||||
R_MIPS_GOT = 9,
|
||||
R_MIPS_PC16 = 10,
|
||||
R_MIPS_CALL = 11, // Call16
|
||||
R_MIPS_GPREL32 = 12,
|
||||
|
||||
R_MIPS_SHIFT5 = 16,
|
||||
R_MIPS_SHIFT6 = 17,
|
||||
R_MIPS_64 = 18,
|
||||
R_MIPS_GOT_DISP = 19,
|
||||
R_MIPS_GOT_PAGE = 20,
|
||||
R_MIPS_GOT_OFST = 21,
|
||||
R_MIPS_GOT_HI16 = 22,
|
||||
R_MIPS_GOT_LO16 = 23,
|
||||
R_MIPS_SUB = 24,
|
||||
R_MIPS_INSERT_A = 25,
|
||||
R_MIPS_INSERT_B = 26,
|
||||
R_MIPS_DELETE = 27,
|
||||
R_MIPS_HIGHER = 28,
|
||||
R_MIPS_HIGHEST = 29,
|
||||
R_MIPS_CALL_HI16 = 30,
|
||||
R_MIPS_CALL_LO16 = 31,
|
||||
R_MIPS_SCN_DISP = 32,
|
||||
R_MIPS_REL16 = 33,
|
||||
R_MIPS_ADD_IMMEDIATE = 34,
|
||||
R_MIPS_PJUMP = 35,
|
||||
R_MIPS_RELGOT = 36,
|
||||
R_MIPS_JALR = 37,
|
||||
R_MIPS_TLS_DTPMOD32 = 38,
|
||||
R_MIPS_TLS_DTPREL32 = 39,
|
||||
R_MIPS_TLS_DTPMOD64 = 40,
|
||||
R_MIPS_TLS_DTPREL64 = 41,
|
||||
R_MIPS_TLS_GD = 42,
|
||||
R_MIPS_TLS_LDM = 43,
|
||||
R_MIPS_TLS_DTPREL_HI16 = 44,
|
||||
R_MIPS_TLS_DTPREL_LO16 = 45,
|
||||
R_MIPS_TLS_GOTTPREL = 46,
|
||||
R_MIPS_TLS_TPREL32 = 47,
|
||||
R_MIPS_TLS_TPREL64 = 48,
|
||||
R_MIPS_TLS_TPREL_HI16 = 49,
|
||||
R_MIPS_TLS_TPREL_LO16 = 50,
|
||||
|
||||
R_MIPS_GLOB_DAT = 51,
|
||||
R_MIPS_PC21_S2 = 60,
|
||||
R_MIPS_PC26_S2 = 61,
|
||||
R_MIPS_PC18_S3 = 62,
|
||||
R_MIPS_PC19_S2 = 63,
|
||||
R_MIPS_PCHI16 = 64,
|
||||
R_MIPS_PCLO16 = 65,
|
||||
|
||||
R_MIPS16_26 = 100,
|
||||
R_MIPS16_GPREL = 101,
|
||||
R_MIPS16_GOT16 = 102,
|
||||
R_MIPS16_CALL16 = 103,
|
||||
R_MIPS16_HI16 = 104,
|
||||
R_MIPS16_LO16 = 105,
|
||||
|
||||
R_MIPS16_TLS_GD = 106,
|
||||
R_MIPS16_TLS_LDM = 107,
|
||||
R_MIPS16_TLS_DTPREL_HI16= 108,
|
||||
R_MIPS16_TLS_DTPREL_LO16= 109,
|
||||
R_MIPS16_TLS_GOTTPREL = 110,
|
||||
R_MIPS16_TLS_TPREL_HI16 = 111,
|
||||
R_MIPS16_TLS_TPREL_LO16 = 112,
|
||||
R_MIPS16_PC16_S1 = 113,
|
||||
|
||||
// For these two:
|
||||
// http://sourceware.org/ml/binutils/2008-07/txt00000.txt
|
||||
R_MIPS_COPY = 126,
|
||||
R_MIPS_JUMP_SLOT = 127,
|
||||
|
||||
// from binutils/include/elf/mips.h
|
||||
R_MICROMIPS_26_S1 = 133,
|
||||
R_MICROMIPS_HI16 = 134,
|
||||
R_MICROMIPS_LO16 = 135,
|
||||
R_MICROMIPS_GPREL16 = 136,
|
||||
R_MICROMIPS_LITERAL = 137,
|
||||
R_MICROMIPS_GOT16 = 138,
|
||||
R_MICROMIPS_PC7_S1 = 139,
|
||||
R_MICROMIPS_PC10_S1 = 140,
|
||||
R_MICROMIPS_PC16_S1 = 141,
|
||||
R_MICROMIPS_CALL16 = 142,
|
||||
R_MICROMIPS_GOT_DISP = 145,
|
||||
R_MICROMIPS_GOT_PAGE = 146,
|
||||
R_MICROMIPS_GOT_OFST = 147,
|
||||
R_MICROMIPS_GOT_HI16 = 148,
|
||||
R_MICROMIPS_GOT_LO16 = 149,
|
||||
R_MICROMIPS_SUB = 150,
|
||||
R_MICROMIPS_HIGHER = 151,
|
||||
R_MICROMIPS_HIGHEST = 152,
|
||||
R_MICROMIPS_CALL_HI16 = 153,
|
||||
R_MICROMIPS_CALL_LO16 = 154,
|
||||
R_MICROMIPS_SCN_DISP = 155,
|
||||
R_MICROMIPS_JALR = 156,
|
||||
R_MICROMIPS_HI0_LO16 = 157,
|
||||
/* TLS relocations. */
|
||||
R_MICROMIPS_TLS_GD = 162,
|
||||
R_MICROMIPS_TLS_LDM = 163,
|
||||
R_MICROMIPS_TLS_DTPREL_HI16 = 164,
|
||||
R_MICROMIPS_TLS_DTPREL_LO16 = 165,
|
||||
R_MICROMIPS_TLS_GOTTPREL = 166,
|
||||
R_MICROMIPS_TLS_TPREL_HI16 = 169,
|
||||
R_MICROMIPS_TLS_TPREL_LO16 = 170,
|
||||
/* microMIPS GP- and PC-relative relocations. */
|
||||
R_MICROMIPS_GPREL7_S2 = 172,
|
||||
R_MICROMIPS_PC23_S2 = 173,
|
||||
|
||||
R_MIPS_PC32 = 248,
|
||||
R_MIPS_EH = 249,
|
||||
R_MIPS_GNU_REL16_S2 = 250,
|
||||
R_MIPS_GNU_VTINHERIT = 253,
|
||||
R_MIPS_GNU_VTENTRY = 254,
|
||||
|
||||
// artificial types for the complex 32bit relocs
|
||||
R_MIPS_GPDISP_LO16 = 200,
|
||||
R_MIPS_GPDISP_HI16 = 201,
|
||||
R_MICROMIPS_GPDISP_HI16 = 202,
|
||||
R_MICROMIPS_GPDISP_LO16 = 203,
|
||||
};
|
||||
|
||||
enum elf_ET_MIPS
|
||||
{
|
||||
ET_IRX = 0xFF80u, // IRX file for PS2's IOP
|
||||
ET_PSPEXEC = 0xFFA0u // Sony PSP executable file
|
||||
};
|
||||
|
||||
enum elf_PHT_MIPS
|
||||
{
|
||||
PT_MIPS_IOPMOD = 0x70000080, // Sony PS2 IOP module extension
|
||||
PT_MIPS_EEMOD = 0x70000090, // Sony PS2 EE module extension
|
||||
PT_MIPS_PSPREL = 0x700000A0, // Sony PRX relocations (ELF-style)
|
||||
PT_MIPS_PSPREL2 = 0x700000A1, // Sony PRX relocations (packed)
|
||||
|
||||
// From binutils-2.27/elfcpp/elfcpp.h
|
||||
PT_MIPS_REGINFO = 0x70000000, // Register usage information. Identifies one .reginfo section.
|
||||
PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table.
|
||||
PT_MIPS_OPTIONS = 0x70000002, // .MIPS.options section.
|
||||
PT_MIPS_ABIFLAGS = 0x70000003, // .MIPS.abiflags section.
|
||||
};
|
||||
|
||||
enum elf_DTAG_MIPS
|
||||
{
|
||||
DT_MIPS_RLD_VERSION = 0x70000001, /* 32 bit version number for runtime linker interface. */
|
||||
DT_MIPS_TIME_STAMP = 0x70000002, /* Time stamp. */
|
||||
DT_MIPS_ICHECKSUM = 0x70000003, /* Checksum of external strings and common sizes. */
|
||||
DT_MIPS_IVERSION = 0x70000004, /* Index of version string in string table. */
|
||||
DT_MIPS_FLAGS = 0x70000005, /* 32 bits of flags. */
|
||||
DT_MIPS_BASE_ADDRESS = 0x70000006, /* Base address of the segment. */
|
||||
DT_MIPS_MSYM = 0x70000007, /* adress of the msym table */
|
||||
DT_MIPS_CONFLICT = 0x70000008, /* Address of .conflict section. */
|
||||
DT_MIPS_LIBLIST = 0x70000009, /* Address of .liblist section. */
|
||||
DT_MIPS_LOCAL_GOTNO = 0x7000000a, /* Number of local global offset table entries. */
|
||||
DT_MIPS_CONFLICTNO = 0x7000000b, /* Number of entries in the .conflict section. */
|
||||
DT_MIPS_LIBLISTNO = 0x70000010, /* Number of entries in the .liblist section. */
|
||||
DT_MIPS_SYMTABNO = 0x70000011, /* Number of entries in the .dynsym section. */
|
||||
DT_MIPS_UNREFEXTNO = 0x70000012, /* Index of first external dynamic symbol not referenced locally. */
|
||||
DT_MIPS_GOTSYM = 0x70000013, /* Index of first dynamic symbol in global offset table. */
|
||||
DT_MIPS_HIPAGENO = 0x70000014, /* Number of page table entries in global offset table. */
|
||||
DT_MIPS_RLD_MAP = 0x70000016, /* Address of run time loader map, used for debugging. */
|
||||
DT_MIPS_DELTA_CLASS = 0x70000017, /* Delta C++ class definition. */
|
||||
DT_MIPS_DELTA_CLASS_NO = 0x70000018, /* Number of entries in DT_MIPS_DELTA_CLASS. */
|
||||
DT_MIPS_DELTA_INSTANCE = 0x70000019, /* Delta C++ class instances. */
|
||||
DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a, /* Number of entries in DT_MIPS_DELTA_INSTANCE. */
|
||||
DT_MIPS_DELTA_RELOC = 0x7000001b, /* Delta relocations. */
|
||||
DT_MIPS_DELTA_RELOC_NO = 0x7000001c, /* Number of entries in DT_MIPS_DELTA_RELOC. */
|
||||
DT_MIPS_DELTA_SYM = 0x7000001d, /* Delta symbols that Delta relocations refer to. */
|
||||
DT_MIPS_DELTA_SYM_NO = 0x7000001e, /* Number of entries in DT_MIPS_DELTA_SYM. */
|
||||
DT_MIPS_DELTA_CLASSSYM = 0x70000020, /* Delta symbols that hold class declarations. */
|
||||
DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, /* Number of entries in DT_MIPS_DELTA_CLASSSYM. */
|
||||
DT_MIPS_CXX_FLAGS = 0x70000022, /* Flags indicating information about C++ flavor. */
|
||||
DT_MIPS_PIXIE_INIT = 0x70000023, /* Pixie information (???). */
|
||||
DT_MIPS_SYMBOL_LIB = 0x70000024, /* Address of .MIPS.symlib */
|
||||
DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, /* The GOT index of the first PTE for a segment */
|
||||
DT_MIPS_LOCAL_GOTIDX = 0x70000026, /* The GOT index of the first PTE for a local symbol */
|
||||
DT_MIPS_HIDDEN_GOTIDX = 0x70000027, /* The GOT index of the first PTE for a hidden symbol */
|
||||
DT_MIPS_PROTECTED_GOTIDX = 0x70000028, /* The GOT index of the first PTE for a protected symbol */
|
||||
DT_MIPS_OPTIONS = 0x70000029, /* Address of `.MIPS.options'. */
|
||||
DT_MIPS_INTERFACE = 0x7000002a, /* Address of `.interface'. */
|
||||
DT_MIPS_DYNSTR_ALIGN = 0x7000002b, /* ??? */
|
||||
DT_MIPS_INTERFACE_SIZE = 0x7000002c, /* Size of the .interface section. */
|
||||
DT_MIPS_RLD_TEXT_RESOLVE_ADDR= 0x7000002d, /* Size of rld_text_resolve function stored in the GOT. */
|
||||
DT_MIPS_PERF_SUFFIX = 0x7000002e, /* Default suffix of DSO to be added by rld on dlopen() calls. */
|
||||
DT_MIPS_COMPACT_SIZE = 0x7000002f, /* Size of compact relocation section (O32). */
|
||||
DT_MIPS_GP_VALUE = 0x70000030, /* GP value for auxiliary GOTs. */
|
||||
DT_MIPS_AUX_DYNAMIC = 0x70000031, /* Address of auxiliary .dynamic. */
|
||||
DT_MIPS_PLTGOT = 0x70000032, /* Address of the base of the PLTGOT */
|
||||
DT_MIPS_RWPLT = 0x70000034, /* Points to the base of a writable PLT. */
|
||||
};
|
||||
|
||||
enum elf_SHN_MIPS
|
||||
{
|
||||
SHN_MIPS_ACOMMON = 0xff00, // Defined and allocated common symbol. Value is virtual address.
|
||||
SHN_MIPS_TEXT = 0xff01, // Defined and allocated text symbol. Value is virtual address.
|
||||
SHN_MIPS_DATA = 0xff02, // Defined and allocated data symbol. Value is virtual address.
|
||||
SHN_MIPS_SCOMMON = 0xff03, // Small common symbol.
|
||||
SHN_MIPS_SUNDEFINED = 0xff04 // Small undefined symbol.
|
||||
};
|
||||
|
||||
enum elf_SHF_MIPS
|
||||
{
|
||||
SHF_MIPS_GPREL = 0x10000000, // Section must be part of global data area.
|
||||
SHF_MIPS_MERGE = 0x20000000, // Section data should be merged to eliminate duplication
|
||||
SHF_MIPS_ADDR = 0x40000000, // Section data is addresses by default. Address size to be inferred from section entry size.
|
||||
SHF_MIPS_STRING = 0x80000000, // Section data is string data by default
|
||||
SHF_MIPS_NOSTRIP = 0x08000000, // Section data may not be stripped
|
||||
SHF_MIPS_LOCAL = 0x04000000, // Section data local to process
|
||||
SHF_MIPS_NAMES = 0x02000000, // Linker must generate implicit hidden weak names
|
||||
SHF_MIPS_NODUPE = 0x01000000, // Section contains text/data which may be replicated in other sections. Linker must retain only one copy.
|
||||
};
|
||||
|
||||
enum elf_SHT_MIPS
|
||||
{
|
||||
SHT_MIPS_LIBLIST = 0x70000000, // contains the set of dynamic shared objects used when statically linking.
|
||||
SHT_MIPS_MSYM = 0x70000001, // unknown Irix5 usage
|
||||
SHT_MIPS_CONFLICT = 0x70000002, // list of confliction symbols
|
||||
SHT_MIPS_GPTAB = 0x70000003, // Section contains the global pointer table.
|
||||
SHT_MIPS_UCODE = 0x70000004, // microcode information
|
||||
SHT_MIPS_DEBUG = 0x70000005, // start of debugging information
|
||||
SHT_MIPS_REGINFO = 0x70000006, // Section contains register usage information.
|
||||
SHT_MIPS_RELD = 0x70000009, // Dynamic relocation?
|
||||
SHT_MIPS_IFACE = 0x7000000B, // Subprogram interface information
|
||||
SHT_MIPS_CONTENT = 0x7000000C, // Section content classification
|
||||
SHT_MIPS_OPTIONS = 0x7000000D, // General options
|
||||
SHT_MIPS_DELTASYM = 0x7000001B, // Delta C++: symbol table
|
||||
SHT_MIPS_DELTAINST = 0x7000001C, // Delta C++: instance table
|
||||
SHT_MIPS_DELTACLASS = 0x7000001D, // Delta C++: class table
|
||||
SHT_MIPS_DWARF = 0x7000001E, // DWARF debugging section.
|
||||
SHT_MIPS_DELTADECL = 0x7000001F, // Delta C++: declarations
|
||||
SHT_MIPS_SYMBOL_LIB = 0x70000020, // unknown Irix6 usage
|
||||
SHT_MIPS_EVENTS = 0x70000021, // Events section.
|
||||
SHT_MIPS_TRANSLATE = 0x70000022, // ???
|
||||
SHT_MIPS_PIXIE = 0x70000023, // Special pixie sections
|
||||
SHT_MIPS_XLATE = 0x70000024, // Address translation table
|
||||
SHT_MIPS_XLATE_DEBUG = 0x70000025, // SGI internal address translation table
|
||||
SHT_MIPS_WHIRL = 0x70000026, // Intermediate code
|
||||
SHT_MIPS_EH_REGION = 0x70000027, // C++ exception handling region info
|
||||
SHT_MIPS_XLATE_OLD = 0x70000028, // Obsolete
|
||||
SHT_MIPS_PDR_EXCEPTION = 0x70000029, // Runtime procedure descriptor table exception information (ucode)
|
||||
SHT_MIPS_IOPMOD = 0x70000080, // .ipmod section for PS2 IRXs
|
||||
SHT_MIPS_PSPREL = 0x700000A0, // PSP executable relocation section
|
||||
// VU overlay table (PS2?)
|
||||
SHT_DVP_OVERLAY_TABLE = 0x7FFFF420,
|
||||
SHT_DVP_OVERLAY = 0x7FFFF421,
|
||||
};
|
||||
|
||||
// Special values for the st_other field in the symbol table.
|
||||
enum elf_STO_MIPS
|
||||
{
|
||||
// Two topmost bits denote the MIPS ISA for .text symbols:
|
||||
// + 00 -- standard MIPS code,
|
||||
// + 10 -- microMIPS code,
|
||||
// + 11 -- MIPS16 code; requires the following two bits to be set too.
|
||||
// Note that one of the MIPS16 bits overlaps with STO_MIPS_PIC.
|
||||
STO_MIPS_ISA = 0xc0,
|
||||
|
||||
// The MIPS psABI was updated in 2008 with support for PLTs and copy
|
||||
// relocs. There are therefore two types of nonzero SHN_UNDEF functions:
|
||||
// PLT entries and traditional MIPS lazy binding stubs. We mark the former
|
||||
// with STO_MIPS_PLT to distinguish them from the latter.
|
||||
STO_MIPS_PLT = 0x8,
|
||||
|
||||
// This value is used to mark PIC functions in an object that mixes
|
||||
// PIC and non-PIC. Note that this bit overlaps with STO_MIPS16,
|
||||
// although MIPS16 symbols are never considered to be MIPS_PIC.
|
||||
STO_MIPS_PIC = 0x20,
|
||||
|
||||
// This value is used for a mips16 .text symbol.
|
||||
STO_MIPS16 = 0xf0,
|
||||
|
||||
// This value is used for a microMIPS .text symbol. To distinguish from
|
||||
// STO_MIPS16, we set top two bits to be 10 to denote STO_MICROMIPS. The
|
||||
// mask is STO_MIPS_ISA.
|
||||
STO_MICROMIPS = 0x80
|
||||
};
|
||||
|
||||
// .MIPS.options descriptor kinds
|
||||
enum elf_ODK_MIPS
|
||||
{
|
||||
ODK_NULL = 0, // Undefined
|
||||
ODK_REGINFO = 1, // Register usage information
|
||||
ODK_EXCEPTIONS = 2, // Exception processing options
|
||||
ODK_PAD = 3, // Section padding options
|
||||
ODK_HWPATCH = 4, // Hardware patches applied
|
||||
ODK_FILL = 5, // Linker fill value
|
||||
ODK_TAGS = 6, // Space for tool identification
|
||||
ODK_HWAND = 7, // Hardware AND patches applied
|
||||
ODK_HWOR = 8, // Hardware OR patches applied
|
||||
ODK_GP_GROUP = 9, // GP group to use for text/data sections
|
||||
ODK_IDENT = 10, // ID information
|
||||
ODK_PAGESIZE = 11, // Page size information
|
||||
};
|
||||
|
||||
// PSP-specific encoding of r_info field
|
||||
// segment in which the relocation resides
|
||||
// i.e. relocation is at pht[ofs_base].p_vaddr + r_offset
|
||||
#define ELF32_R_OFS_BASE(i) (((i)>>8) & 0xFF)
|
||||
// segment number with the target
|
||||
// i.e. the final address should be adjusted with pht[ofs_base].p_vaddr
|
||||
#define ELF32_R_ADDR_BASE(i) (((i)>>16) & 0xFF)
|
||||
|
||||
|
||||
// MIPS ELF 64 relocation info access macros.
|
||||
// they assume BE byte order of the packed r_type field
|
||||
#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff)
|
||||
#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff)
|
||||
#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff)
|
||||
#define ELF64_MIPS_R_TYPE(i) ((i) & 0xff)
|
||||
|
||||
// Values found in the r_ssym field of a relocation entry.
|
||||
// No relocation.
|
||||
#define RSS_UNDEF 0
|
||||
// Value of GP.
|
||||
#define RSS_GP 1
|
||||
// Value of GP in object being relocated.
|
||||
#define RSS_GP0 2
|
||||
// Address of location being relocated.
|
||||
#define RSS_LOC 3
|
||||
|
||||
// MIPS .msym table entry
|
||||
struct Elf32_Msym
|
||||
{
|
||||
uint32 ms_hash_value; // Contains the hash value computed from the name of the corresponding dynamic symbol
|
||||
uint32 ms_info; // Contains both the dynamic relocation index and the symbol flags field.
|
||||
};
|
||||
|
||||
#define ELF32_MS_REL_INDEX(i) ((i) >> 8)
|
||||
#define ELF32_MS_FLAGS(i) ((i) & 0xff)
|
||||
#define ELF32_MS_INFO(r,f) (((r) << 8) + ((f) & 0xff))
|
||||
|
||||
// MIPS .liblist entry
|
||||
typedef struct
|
||||
{
|
||||
uint32 l_name; // Records the name of a shared library dependency.
|
||||
// The value is a string table index. This name can be a
|
||||
// full pathname, relative pathname, or file name.
|
||||
uint32 l_time_stamp;// Records the time stamp of a shared library dependency.
|
||||
uint32 l_checksum; // Records the checksum of a shared library dependency.
|
||||
uint32 l_version; // Records the interface version of a shared library dependency.
|
||||
// The value is a string table index.
|
||||
uint32 l_flags;
|
||||
} Elf64_Lib;
|
||||
|
||||
// bits for l_flags:
|
||||
#define LL_NONE 0
|
||||
#define LL_EXACT_MATCH 0x1 // Requires that the run-time dynamic shared library file match
|
||||
// exactly the shared library file used at static link time.
|
||||
#define LL_IGNORE_INT_VER 0x2 // Ignores any version incompatibility between the dynamic
|
||||
// shared library file and the shared library file used at link time.
|
||||
#define LL_REQUIRE_MINOR 0x4 // Marks shared library dependencies that should be loaded with
|
||||
// a suffix appended to the name. The DT_SO_SUFFIX entry in
|
||||
// the .dynamic section records the name of this suffix. This is
|
||||
// used by object instrumentation tools to distinguish
|
||||
// instrumented shared libraries.
|
||||
#define LL_EXPORTS 0x8 // Marks entries for shared libraries that are not loaded as direct
|
||||
// dependencies of an object.
|
||||
#define LL_DELAY_LOAD 0x10
|
||||
#define LL_DELTA 0x20
|
||||
|
||||
//.reginfo section
|
||||
struct Elf32_RegInfo
|
||||
{
|
||||
uint32 ri_gprmask;
|
||||
uint32 ri_cprmask[4];
|
||||
uint32 ri_gp_value;
|
||||
};
|
||||
|
||||
void set_mips_compact_encoding(ea_t ea, bool enable);
|
||||
void relocate_psp_section(Elf64_Shdr *rsh, linput_t *li);
|
||||
inline bool is_psp_file(const reader_t &reader)
|
||||
{
|
||||
return reader.get_header().e_machine == EM_MIPS
|
||||
&& reader.get_header().e_type == ET_PSPEXEC;
|
||||
}
|
||||
|
||||
#endif
|
||||
383
idasdk76/ldr/elf/elfr_ppc.h
Normal file
383
idasdk76/ldr/elf/elfr_ppc.h
Normal file
@@ -0,0 +1,383 @@
|
||||
#ifndef __ELFR_PPC_H__
|
||||
#define __ELFR_PPC_H__
|
||||
|
||||
#ifndef __ELFBASE_H__
|
||||
#include "elfbase.h"
|
||||
#endif
|
||||
|
||||
#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
|
||||
#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag */
|
||||
#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag */
|
||||
|
||||
// PowerPC 64 ABI version
|
||||
#define EF_PPC64_ABI_MASK 3 // original function descriptor using ABI
|
||||
#define EF_PPC64_UNK_ABI 0 // unspecified or not using any features
|
||||
// affected by the differences
|
||||
#define EF_PPC64_AIX_ABI 1 // original function descriptor using ABI
|
||||
#define EF_PPC64_V2_ABI 2 // revised ABI without function descriptors
|
||||
|
||||
enum elf_ET_PPC
|
||||
{
|
||||
ET_PS3PRX = 0xFFA4, // Sony PS3 PRX
|
||||
};
|
||||
|
||||
enum elf_SHT_PPC
|
||||
{
|
||||
SHT_PS3PRX_RELA = 0x700000A4, // Sony PS3 PRX relocations
|
||||
};
|
||||
|
||||
enum elf_PHT_PPC
|
||||
{
|
||||
PHT_PS3PRX_RELA = 0x700000A4, // Sony PS3 PRX relocations
|
||||
};
|
||||
|
||||
enum elf_DT_PPC
|
||||
{
|
||||
DT_PPC_GOT = (DT_LOPROC + 0x0), // address of _GLOBAL_OFFSET_TABLE_
|
||||
};
|
||||
|
||||
// relocation field - word32 with HIGH BYTE FIRST!!!
|
||||
// A- from Elf32_Rela
|
||||
// B- Loading address of shared object
|
||||
// G- offset into global objet table
|
||||
// GOT- adress of global object table
|
||||
// L- linkage table entry
|
||||
// P- plase of storage unit (computed using r_offset)
|
||||
// S- value of symbol
|
||||
enum elf_RTYPE_ppc
|
||||
{
|
||||
R_PPC_NONE = 0, // No reloc
|
||||
R_PPC_ADDR32 = 1, // S+A-P Direct 32 bit
|
||||
R_PPC_ADDR24 = 2,
|
||||
R_PPC_ADDR16 = 3,
|
||||
R_PPC_ADDR16_LO = 4,
|
||||
R_PPC_ADDR16_HI = 5,
|
||||
R_PPC_ADDR16_HA = 6,
|
||||
R_PPC_ADDR14 = 7,
|
||||
R_PPC_ADDR14_BRTAKEN = 8,
|
||||
R_PPC_ADDR14_BRNTAKEN = 9,
|
||||
R_PPC_REL24 = 10, // S+A relative 24 bit
|
||||
R_PPC_REL14 = 11,
|
||||
R_PPC_REL14_BRTAKEN = 12,
|
||||
R_PPC_REL14_BRNTAKEN = 13,
|
||||
R_PPC_GOT16 = 14,
|
||||
R_PPC_GOT16_LO = 15,
|
||||
R_PPC_GOT16_HI = 16,
|
||||
R_PPC_GOT16_HA = 17,
|
||||
R_PPC_PLTREL24 = 18,
|
||||
R_PPC_COPY = 19,
|
||||
R_PPC_GLOB_DAT = 20,
|
||||
R_PPC_JMP_SLOT = 21,
|
||||
R_PPC_RELATIVE = 22,
|
||||
R_PPC_LOCAL24PC = 23,
|
||||
R_PPC_UADDR32 = 24,
|
||||
R_PPC_UADDR16 = 25,
|
||||
R_PPC_REL32 = 26,
|
||||
R_PPC_PLT32 = 27,
|
||||
R_PPC_PLTREL32 = 28,
|
||||
R_PPC_PLT16_LO = 29,
|
||||
R_PPC_PLT16_HI = 30,
|
||||
R_PPC_PLT16_HA = 31,
|
||||
R_PPC_SDAREL16 = 32,
|
||||
R_PPC_SECTOFF = 33,
|
||||
R_PPC_SECTOFF_LO = 34,
|
||||
R_PPC_SECTOFF_HI = 35,
|
||||
R_PPC_SECTOFF_HA = 36,
|
||||
R_PPC_ADDR30 = 37, // word30 (S + A - P) >> 2
|
||||
|
||||
|
||||
// some undocumented relocs used by freescale
|
||||
// some seem to be the same as official VLE relocs below
|
||||
// NB! they conflict with some PPC64 relocations
|
||||
R_PPC_FVLE_REL8 = 38, // same as R_PPC_VLE_REL8?
|
||||
R_PPC_FVLE_REL15 = 39, // same as R_PPC_VLE_REL15?
|
||||
R_PPC_FVLE_REL24 = 40, // same as R_PPC_VLE_REL24?
|
||||
R_PPC_FVLE_ADDR8 = 44, // ??
|
||||
R_PPC_FVLE_ADDR4 = 45, // ??
|
||||
R_PPC_FVLE_SDA = 47, // same as R_PPC_VLE_SDA21?
|
||||
R_PPC_FVLE_LO16A = 49, // same as R_PPC_VLE_LO16A?
|
||||
R_PPC_FVLE_HI16A = 50, // same as R_PPC_VLE_HI16A?
|
||||
R_PPC_FVLE_HA16A = 51, // same as R_PPC_VLE_HA16A?
|
||||
R_PPC_FVLE_LO16D = 56, // same as R_PPC_VLE_LO16D?
|
||||
R_PPC_FVLE_HI16D = 57, // same as R_PPC_VLE_HI16D?
|
||||
R_PPC_FVLE_HA16D = 58, // same as R_PPC_VLE_HA16D?
|
||||
|
||||
/* Relocs added to support TLS. */
|
||||
R_PPC_TLS = 67,
|
||||
R_PPC_DTPMOD32 = 68,
|
||||
R_PPC_TPREL16 = 69,
|
||||
R_PPC_TPREL16_LO = 70,
|
||||
R_PPC_TPREL16_HI = 71,
|
||||
R_PPC_TPREL16_HA = 72,
|
||||
R_PPC_TPREL32 = 73,
|
||||
R_PPC_DTPREL16 = 74,
|
||||
R_PPC_DTPREL16_LO = 75,
|
||||
R_PPC_DTPREL16_HI = 76,
|
||||
R_PPC_DTPREL16_HA = 77,
|
||||
R_PPC_DTPREL32 = 78,
|
||||
R_PPC_GOT_TLSGD16 = 79,
|
||||
R_PPC_GOT_TLSGD16_LO = 80,
|
||||
R_PPC_GOT_TLSGD16_HI = 81,
|
||||
R_PPC_GOT_TLSGD16_HA = 82,
|
||||
R_PPC_GOT_TLSLD16 = 83,
|
||||
R_PPC_GOT_TLSLD16_LO = 84,
|
||||
R_PPC_GOT_TLSLD16_HI = 85,
|
||||
R_PPC_GOT_TLSLD16_HA = 86,
|
||||
R_PPC_GOT_TPREL16 = 87,
|
||||
R_PPC_GOT_TPREL16_LO = 88,
|
||||
R_PPC_GOT_TPREL16_HI = 89,
|
||||
R_PPC_GOT_TPREL16_HA = 90,
|
||||
R_PPC_GOT_DTPREL16 = 91,
|
||||
R_PPC_GOT_DTPREL16_LO = 92,
|
||||
R_PPC_GOT_DTPREL16_HI = 93,
|
||||
R_PPC_GOT_DTPREL16_HA = 94,
|
||||
R_PPC_TLSGD = 95,
|
||||
R_PPC_TLSLD = 96,
|
||||
|
||||
R_PPC_EMB_NADDR32 = 101, // word32 (A - S)
|
||||
R_PPC_EMB_NADDR16 = 102, // half16* (A - S)
|
||||
R_PPC_EMB_NADDR16_LO = 103, // half16 #lo(A - S)
|
||||
R_PPC_EMB_NADDR16_HI = 104, // half16 #hi(A - S)
|
||||
R_PPC_EMB_NADDR16_HA = 105, // half16 #ha(A - S)
|
||||
R_PPC_EMB_SDA_I16 = 106, // half16* T
|
||||
R_PPC_EMB_SDA2_I16 = 107, // half16* U
|
||||
R_PPC_EMB_SDA2REL = 108, // half16* S + A - _SDA2_BASE_
|
||||
R_PPC_EMB_SDA21 = 109, // low21 Y || (X + A)
|
||||
R_PPC_EMB_MRKREF = 110, // none See below
|
||||
R_PPC_EMB_RELSEC16 = 111, // half16* V + A
|
||||
R_PPC_EMB_RELST_LO = 112, // half16 #lo(W + A)
|
||||
R_PPC_EMB_RELST_HI = 113, // half16 #hi(W + A)
|
||||
R_PPC_EMB_RELST_HA = 114, // half16 #ha(W + A)
|
||||
R_PPC_EMB_BIT_FLD = 115, // word32* See below
|
||||
R_PPC_EMB_RELSDA = 116, // half16* X + A. See below
|
||||
R_PPC_EMB_RELOC_120 = 120, // half16* S + A
|
||||
R_PPC_EMB_RELOC_121 = 121, // half16* Same calculation as U, except that the value 0 is used instead of _SDA2_BASE_.
|
||||
|
||||
/* The R_PPC_DIAB_SDA21_xx relocation modes work like the R_PPC_EMB_SDA21 mode
|
||||
* and the R_PPC_DIAB_RELSDA_xx relocation modes work like the R_PPC_EMB_RELSDA mode
|
||||
* with the following exceptions:
|
||||
* If the symbol is in .data, .sdata, .bss, .sbss the symbol is DATA relative
|
||||
(r13 base pointer/_SDA_BASE_ base address)
|
||||
* If the symbol is in .text, .sdata2, .sbss2 the symbol is CODE relative
|
||||
(r2 base pointer/_SDA_BASE2_ base address)
|
||||
* Otherwise the symbol is absolute (r0 base pointer/0 base address)
|
||||
*/
|
||||
R_PPC_DIAB_SDA21_LO = 180, // half21 Y || #lo(X + A)
|
||||
R_PPC_DIAB_SDA21_HI = 181, // half21 Y || #hi(X + A)
|
||||
R_PPC_DIAB_SDA21_HA = 182, // half21 Y || #ha(X + A)
|
||||
R_PPC_DIAB_RELSDA_LO = 183, // half16 #lo(X + A)
|
||||
R_PPC_DIAB_RELSDA_HI = 184, // half16 #hi(X + A)
|
||||
R_PPC_DIAB_RELSDA_HA = 185, // half16 #ha(X + A)
|
||||
R_PPC_DIAB_IMTO = 186,
|
||||
R_PPC_DIAB_IMT = 187,
|
||||
R_PPC_DIAB_ADDR0 = 188,
|
||||
R_PPC_DIAB_OVERRIDE0 = 189,
|
||||
R_PPC_DIAB_VTBL32 = 190,
|
||||
R_PPC_DIAB_LAST = 191,
|
||||
|
||||
R_PPC_EMB_SPE_DOUBLE = 201, // mid5* (#lo(S + A)) >> 3
|
||||
R_PPC_EMB_SPE_WORD = 202, // mid5* (#lo(S + A)) >> 2
|
||||
R_PPC_EMB_SPE_HALF = 203, // mid5* (#lo(S + A)) >> 1
|
||||
R_PPC_EMB_SPE_DOUBLE_SDAREL = 204, // mid5* (#lo(S + A - _SDA_BASE_)) >> 3
|
||||
R_PPC_EMB_SPE_WORD_SDAREL = 205, // mid5* (#lo(S + A - _SDA_BASE_)) >> 2
|
||||
R_PPC_EMB_SPE_HALF_SDAREL = 206, // mid5* (#lo(S + A - _SDA_BASE_)) >> 1
|
||||
R_PPC_EMB_SPE_DOUBLE_SDA2REL = 207, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 3
|
||||
R_PPC_EMB_SPE_WORD_SDA2REL = 208, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 2
|
||||
R_PPC_EMB_SPE_HALF_SDA2REL = 209, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 1
|
||||
R_PPC_EMB_SPE_DOUBLE_SDA0REL = 210, // mid5* (#lo(S + A)) >> 3
|
||||
R_PPC_EMB_SPE_WORD_SDA0REL = 211, // mid5* (#lo(S + A)) >> 2
|
||||
R_PPC_EMB_SPE_HALF_SDA0REL = 212, // mid5* (#lo(S + A)) >> 1
|
||||
R_PPC_EMB_SPE_DOUBLE_SDA = 213, // mid10* Y || ((#lo(X + A)) >> 3)
|
||||
R_PPC_EMB_SPE_WORD_SDA = 214, // mid10* Y || ((#lo(X + A)) >> 2)
|
||||
R_PPC_EMB_SPE_HALF_SDA = 215, // mid10* Y || ((#lo(X + A)) >> 1)
|
||||
|
||||
R_PPC_VLE_REL8 = 216, // bdh8 (S + A - P) >> 1
|
||||
R_PPC_VLE_REL15 = 217, // bdh15 (S + A - P) >> 1
|
||||
R_PPC_VLE_REL24 = 218, // bdh24 (S + A - P) >> 1
|
||||
R_PPC_VLE_LO16A = 219, // split16a #lo(S + A)
|
||||
R_PPC_VLE_LO16D = 220, // split16d #lo(S + A)
|
||||
R_PPC_VLE_HI16A = 221, // split16a #hi(S + A)
|
||||
R_PPC_VLE_HI16D = 222, // split16d #hi(S + A)
|
||||
R_PPC_VLE_HA16A = 223, // split16a #ha(S + A)
|
||||
R_PPC_VLE_HA16D = 224, // split16d #ha(S + A)
|
||||
R_PPC_VLE_SDA21 = 225, // low21, split20 Y || (X + A)
|
||||
R_PPC_VLE_SDA21_LO = 226, // low21, split20 Y || #lo(X + A)
|
||||
R_PPC_VLE_SDAREL_LO16A = 227, // split16a #lo(X + A)
|
||||
R_PPC_VLE_SDAREL_LO16D = 228, // split16d #lo(X + A)
|
||||
R_PPC_VLE_SDAREL_HI16A = 229, // split16a #hi(X + A)
|
||||
R_PPC_VLE_SDAREL_HI16D = 230, // split16d #hi(X + A)
|
||||
R_PPC_VLE_SDAREL_HA16A = 231, // split16a #ha(X + A)
|
||||
R_PPC_VLE_SDAREL_HA16D = 232, // split16d #ha(X + A)
|
||||
|
||||
R_PPC_REL16DX_HA = 246,
|
||||
|
||||
R_PPC_IRELATIVE = 248, // GNU extension to support local ifunc.
|
||||
/* GNU relocs used in PIC code sequences. */
|
||||
R_PPC_REL16 = 249, // half16* S + A - P
|
||||
R_PPC_REL16_LO = 250, // half16 #lo(S + A - P)
|
||||
R_PPC_REL16_HI = 251, // half16 #hi(S + A - P)
|
||||
R_PPC_REL16_HA = 252, // half16 #la(S + A - P)
|
||||
|
||||
R_PPC_GNU_VTINHERIT = 253,
|
||||
R_PPC_GNU_VTENTRY = 254,
|
||||
/* This is a phony reloc to handle any old fashioned TOC16 references
|
||||
that may still be in object files. */
|
||||
R_PPC_TOC16 = 255,
|
||||
|
||||
// PowerPC64 relocations. Many (but not all) of them are the same as for PPC32
|
||||
R_PPC64_NONE = R_PPC_NONE,
|
||||
R_PPC64_ADDR32 = R_PPC_ADDR32, /* 32bit absolute address. */
|
||||
R_PPC64_ADDR24 = R_PPC_ADDR24, /* 26bit address, word aligned. */
|
||||
R_PPC64_ADDR16 = R_PPC_ADDR16, /* 16bit absolute address. */
|
||||
R_PPC64_ADDR16_LO = R_PPC_ADDR16_LO, /* lower 16bits of abs. address. */
|
||||
R_PPC64_ADDR16_HI = R_PPC_ADDR16_HI, /* high 16bits of abs. address. */
|
||||
R_PPC64_ADDR16_HA = R_PPC_ADDR16_HA, /* adjusted high 16bits. */
|
||||
R_PPC64_ADDR14 = R_PPC_ADDR14, /* 16bit address, word aligned. */
|
||||
R_PPC64_ADDR14_BRTAKEN = R_PPC_ADDR14_BRTAKEN,
|
||||
R_PPC64_ADDR14_BRNTAKEN = R_PPC_ADDR14_BRNTAKEN,
|
||||
R_PPC64_REL24 = R_PPC_REL24, /* PC relative 26 bit, word aligned. */
|
||||
R_PPC64_REL14 = R_PPC_REL14, /* PC relative 16 bit. */
|
||||
R_PPC64_REL14_BRTAKEN = R_PPC_REL14_BRTAKEN,
|
||||
R_PPC64_REL14_BRNTAKEN = R_PPC_REL14_BRNTAKEN,
|
||||
R_PPC64_GOT16 = R_PPC_GOT16,
|
||||
R_PPC64_GOT16_LO = R_PPC_GOT16_LO,
|
||||
R_PPC64_GOT16_HI = R_PPC_GOT16_HI,
|
||||
R_PPC64_GOT16_HA = R_PPC_GOT16_HA,
|
||||
R_PPC64_PLTREL24 = R_PPC_PLTREL24,
|
||||
R_PPC64_COPY = R_PPC_COPY,
|
||||
R_PPC64_GLOB_DAT = R_PPC_GLOB_DAT,
|
||||
R_PPC64_JMP_SLOT = R_PPC_JMP_SLOT,
|
||||
R_PPC64_RELATIVE = R_PPC_RELATIVE,
|
||||
R_PPC64_LOCAL24PC = R_PPC_LOCAL24PC,
|
||||
R_PPC64_UADDR32 = R_PPC_UADDR32,
|
||||
R_PPC64_UADDR16 = R_PPC_UADDR16,
|
||||
R_PPC64_REL32 = R_PPC_REL32,
|
||||
R_PPC64_PLT32 = R_PPC_PLT32,
|
||||
R_PPC64_PLTREL32 = R_PPC_PLTREL32,
|
||||
R_PPC64_PLT16_LO = R_PPC_PLT16_LO,
|
||||
R_PPC64_PLT16_HI = R_PPC_PLT16_HI,
|
||||
R_PPC64_PLT16_HA = R_PPC_PLT16_HA,
|
||||
R_PPC64_SDAREL16 = R_PPC_SDAREL16,
|
||||
R_PPC64_SECTOFF = R_PPC_SECTOFF,
|
||||
R_PPC64_SECTOFF_LO = R_PPC_SECTOFF_LO,
|
||||
R_PPC64_SECTOFF_HI = R_PPC_SECTOFF_HI,
|
||||
R_PPC64_SECTOFF_HA = R_PPC_SECTOFF_HA,
|
||||
|
||||
R_PPC64_ADDR30 = 37, /* word30 (S + A - P) >> 2. */
|
||||
R_PPC64_ADDR64 = 38, /* doubleword64 S + A. */
|
||||
R_PPC64_ADDR16_HIGHER = 39, /* half16 #higher(S + A). */
|
||||
R_PPC64_ADDR16_HIGHERA = 40, /* half16 #highera(S + A). */
|
||||
R_PPC64_ADDR16_HIGHEST = 41, /* half16 #highest(S + A). */
|
||||
R_PPC64_ADDR16_HIGHESTA = 42, /* half16 #highesta(S + A). */
|
||||
R_PPC64_UADDR64 = 43, /* doubleword64 S + A. */
|
||||
R_PPC64_REL64 = 44, /* doubleword64 S + A - P. */
|
||||
R_PPC64_PLT64 = 45, /* doubleword64 L + A. */
|
||||
R_PPC64_PLTREL64 = 46, /* doubleword64 L + A - P. */
|
||||
R_PPC64_TOC16 = 47, /* half16* S + A - .TOC. */
|
||||
R_PPC64_TOC16_LO = 48, /* half16 #lo(S + A - .TOC.). */
|
||||
R_PPC64_TOC16_HI = 49, /* half16 #hi(S + A - .TOC.). */
|
||||
R_PPC64_TOC16_HA = 50, /* half16 #ha(S + A - .TOC.). */
|
||||
R_PPC64_TOC = 51, /* doubleword64 .TOC. */
|
||||
R_PPC64_PLTGOT16 = 52, /* half16* M + A. */
|
||||
R_PPC64_PLTGOT16_LO = 53, /* half16 #lo(M + A). */
|
||||
R_PPC64_PLTGOT16_HI = 54, /* half16 #hi(M + A). */
|
||||
R_PPC64_PLTGOT16_HA = 55, /* half16 #ha(M + A). */
|
||||
|
||||
R_PPC64_ADDR16_DS = 56, /* half16ds* (S + A) >> 2. */
|
||||
R_PPC64_ADDR16_LO_DS = 57, /* half16ds #lo(S + A) >> 2. */
|
||||
R_PPC64_GOT16_DS = 58, /* half16ds* (G + A) >> 2. */
|
||||
R_PPC64_GOT16_LO_DS = 59, /* half16ds #lo(G + A) >> 2. */
|
||||
R_PPC64_PLT16_LO_DS = 60, /* half16ds #lo(L + A) >> 2. */
|
||||
R_PPC64_SECTOFF_DS = 61, /* half16ds* (R + A) >> 2. */
|
||||
R_PPC64_SECTOFF_LO_DS = 62, /* half16ds #lo(R + A) >> 2. */
|
||||
R_PPC64_TOC16_DS = 63, /* half16ds* (S + A - .TOC.) >> 2. */
|
||||
R_PPC64_TOC16_LO_DS = 64, /* half16ds #lo(S + A - .TOC.) >> 2. */
|
||||
R_PPC64_PLTGOT16_DS = 65, /* half16ds* (M + A) >> 2. */
|
||||
R_PPC64_PLTGOT16_LO_DS = 66, /* half16ds #lo(M + A) >> 2. */
|
||||
|
||||
/* PowerPC64 relocations defined for the TLS access ABI. */
|
||||
R_PPC64_TLS = 67, /* none (sym+add)@tls */
|
||||
R_PPC64_DTPMOD64 = 68, /* doubleword64 (sym+add)@dtpmod */
|
||||
R_PPC64_TPREL16 = 69, /* half16* (sym+add)@tprel */
|
||||
R_PPC64_TPREL16_LO = 70, /* half16 (sym+add)@tprel@l */
|
||||
R_PPC64_TPREL16_HI = 71, /* half16 (sym+add)@tprel@h */
|
||||
R_PPC64_TPREL16_HA = 72, /* half16 (sym+add)@tprel@ha */
|
||||
R_PPC64_TPREL64 = 73, /* doubleword64 (sym+add)@tprel */
|
||||
R_PPC64_DTPREL16 = 74, /* half16* (sym+add)@dtprel */
|
||||
R_PPC64_DTPREL16_LO = 75, /* half16 (sym+add)@dtprel@l */
|
||||
R_PPC64_DTPREL16_HI = 76, /* half16 (sym+add)@dtprel@h */
|
||||
R_PPC64_DTPREL16_HA = 77, /* half16 (sym+add)@dtprel@ha */
|
||||
R_PPC64_DTPREL64 = 78, /* doubleword64 (sym+add)@dtprel */
|
||||
R_PPC64_GOT_TLSGD16 = 79, /* half16* (sym+add)@got@tlsgd */
|
||||
R_PPC64_GOT_TLSGD16_LO = 80, /* half16 (sym+add)@got@tlsgd@l */
|
||||
R_PPC64_GOT_TLSGD16_HI = 81, /* half16 (sym+add)@got@tlsgd@h */
|
||||
R_PPC64_GOT_TLSGD16_HA = 82, /* half16 (sym+add)@got@tlsgd@ha */
|
||||
R_PPC64_GOT_TLSLD16 = 83, /* half16* (sym+add)@got@tlsld */
|
||||
R_PPC64_GOT_TLSLD16_LO = 84, /* half16 (sym+add)@got@tlsld@l */
|
||||
R_PPC64_GOT_TLSLD16_HI = 85, /* half16 (sym+add)@got@tlsld@h */
|
||||
R_PPC64_GOT_TLSLD16_HA = 86, /* half16 (sym+add)@got@tlsld@ha */
|
||||
R_PPC64_GOT_TPREL16_DS = 87, /* half16ds* (sym+add)@got@tprel */
|
||||
R_PPC64_GOT_TPREL16_LO_DS = 88, /* half16ds (sym+add)@got@tprel@l */
|
||||
R_PPC64_GOT_TPREL16_HI = 89, /* half16 (sym+add)@got@tprel@h */
|
||||
R_PPC64_GOT_TPREL16_HA = 90, /* half16 (sym+add)@got@tprel@ha */
|
||||
R_PPC64_GOT_DTPREL16_DS = 91, /* half16ds* (sym+add)@got@dtprel */
|
||||
R_PPC64_GOT_DTPREL16_LO_DS = 92, /* half16ds (sym+add)@got@dtprel@l */
|
||||
R_PPC64_GOT_DTPREL16_HI = 93, /* half16 (sym+add)@got@dtprel@h */
|
||||
R_PPC64_GOT_DTPREL16_HA = 94, /* half16 (sym+add)@got@dtprel@ha */
|
||||
R_PPC64_TPREL16_DS = 95, /* half16ds* (sym+add)@tprel */
|
||||
R_PPC64_TPREL16_LO_DS = 96, /* half16ds (sym+add)@tprel@l */
|
||||
R_PPC64_TPREL16_HIGHER = 97, /* half16 (sym+add)@tprel@higher */
|
||||
R_PPC64_TPREL16_HIGHERA = 98, /* half16 (sym+add)@tprel@highera */
|
||||
R_PPC64_TPREL16_HIGHEST = 99, /* half16 (sym+add)@tprel@highest */
|
||||
R_PPC64_TPREL16_HIGHESTA = 100, /* half16 (sym+add)@tprel@highesta */
|
||||
R_PPC64_DTPREL16_DS = 101, /* half16ds* (sym+add)@dtprel */
|
||||
R_PPC64_DTPREL16_LO_DS = 102, /* half16ds (sym+add)@dtprel@l */
|
||||
R_PPC64_DTPREL16_HIGHER = 103, /* half16 (sym+add)@dtprel@higher */
|
||||
R_PPC64_DTPREL16_HIGHERA = 104, /* half16 (sym+add)@dtprel@highera */
|
||||
R_PPC64_DTPREL16_HIGHEST = 105, /* half16 (sym+add)@dtprel@highest */
|
||||
R_PPC64_DTPREL16_HIGHESTA = 106, /* half16 (sym+add)@dtprel@highesta */
|
||||
#if 0
|
||||
// These relocation types appear in David Anderson's libdwarf and
|
||||
// dwarfdump only. The PPC 64-Bit ELF V2 ABI uses these numbers for
|
||||
// different types (see below).
|
||||
R_PPC64_TOC32 = 107, /* word32 (.TOC. & 0xffff_ffff) */
|
||||
R_PPC64_DTPMOD32 = 108, /* word32 (@dtpmod & 0xffff_ffff) */
|
||||
R_PPC64_TPREL32 = 109, /* word32 (@tprel & 0xffff_ffff) */
|
||||
R_PPC64_DTPREL32 = 110, /* word32 (@dtprel & 0xffff_ffff) */
|
||||
#else
|
||||
// The PPC 64-Bit ELF V2 ABI uses these numbers for different types
|
||||
R_PPC64_TLSGD = 107, // used as markers on thread local
|
||||
R_PPC64_TLSLD = 108, // storage (TLS) code sequences
|
||||
R_PPC64_TOCSAVE = 109, // this relocation type indicates a
|
||||
// position where a TOC save may be
|
||||
// inserted in the function to avoid a
|
||||
// TOC save as part of the PLT stub code
|
||||
R_PPC64_ADDR16_HIGH = 110, // half16 #hi(S + A)
|
||||
R_PPC64_ADDR16_HIGHA = 111, // half16 #ha(S + A)
|
||||
R_PPC64_TPREL16_HIGH = 112, // half16 #hi(@tprel)
|
||||
R_PPC64_TPREL16_HIGHA = 113, // half16 #ha(@tprel)
|
||||
R_PPC64_DTPREL16_HIGH = 114, // half16 #hi(@dtprel)
|
||||
R_PPC64_DTPREL16_HIGHA = 115, // half16 #ha(@dtprel)
|
||||
R_PPC64_REL24_NOTOC = 116, // low24* (S + A - P) >> 2
|
||||
R_PPC64_ADDR64_LOCAL = 117, // doubleword64 S + A (see 3.5.4)
|
||||
#endif
|
||||
R_PPC64_JMP_IREL = 247, // GNU extension to support local ifunc
|
||||
// The PPC 64-Bit ELF V2 ABI
|
||||
R_PPC64_IRELATIVE = 248, // It is used to implement the
|
||||
// STT_GNU_IFUNC framework
|
||||
R_PPC64_REL16 = R_PPC_REL16, // half16* S + A - P
|
||||
R_PPC64_REL16_LO = R_PPC_REL16_LO, // half16 #lo(S + A - P)
|
||||
R_PPC64_REL16_HI = R_PPC_REL16_HI, // half16* #hi(S + A - P)
|
||||
R_PPC64_REL16_HA = R_PPC_REL16_HA, // half16* #la(S + A - P)
|
||||
};
|
||||
|
||||
// flags for VLE code
|
||||
#define SHF_PPC_VLE 0x10000000 /* section header flag */
|
||||
#define PF_PPC_VLE 0x10000000 /* program header flag */
|
||||
|
||||
// patching GOT loading,
|
||||
// discard auxiliary values in plt/got
|
||||
// can present offset bypass segment
|
||||
#define ELF_RPL_PPC_DEFAULT (ELF_RPL_GL | ELF_DIS_OFFW | ELF_DIS_GPLT)
|
||||
|
||||
#endif
|
||||
3558
idasdk76/ldr/elf/reader.cpp
Normal file
3558
idasdk76/ldr/elf/reader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
4
idasdk76/ldr/exports.def
Normal file
4
idasdk76/ldr/exports.def
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
global: LDSC;
|
||||
local: *;
|
||||
};
|
||||
69
idasdk76/ldr/geos/common.cpp
Normal file
69
idasdk76/ldr/geos/common.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
//--------------------------------------------------------------------------
|
||||
static char *token2str(char *buf, size_t bufsize, GEOStoken &t)
|
||||
{
|
||||
if ( t.str[0] )
|
||||
qsnprintf(buf, bufsize, "%4.4s/%u", t.str, t.num);
|
||||
else
|
||||
qstrncpy(buf, "-", bufsize);
|
||||
return buf;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const unsigned char _GeosXlate[] =
|
||||
{
|
||||
0x8E, 0x8F, 0x80, 0x90, 0xA5, 0x99, 0x9A, 0xA0,
|
||||
0x85, 0x83, 0x84, 0x20, 0x86, 0x87, 0x82, 0x8A,
|
||||
0x88, 0x89, 0xA1, 0x8D, 0x8C, 0x8B, 0xA4, 0xA2,
|
||||
0x95, 0x93, 0x94, 0x20, 0xA3, 0x97, 0x96, 0x81,
|
||||
0x20, 0xF8, 0x9B, 0x9C, 0x15, 0xF9, 0x14, 0xE1,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x92, 0x20,
|
||||
0xEC, 0xF1, 0xF3, 0xF2, 0x9D, 0xE6, 0xEB, 0xE4,
|
||||
0x20, 0x20, 0xF4, 0xA6, 0xA7, 0xEA, 0x91, 0xED,
|
||||
0xA8, 0xAD, 0xAA, 0xFB, 0x9F, 0xF7, 0x20, 0xAE,
|
||||
0xAF, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xF6, 0x04,
|
||||
0x98, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
|
||||
};
|
||||
|
||||
static const unsigned char _GeosXlapp[] =
|
||||
{
|
||||
0x8E, 0x8F, 0x80, 0x90, 0xA5, 0x99, 0x9A, 0xA0,
|
||||
0x85, 0x83, 0x84, 0x61, 0x86, 0x87, 0x82, 0x8A,
|
||||
0x88, 0x89, 0xA1, 0x8D, 0x8C, 0x8B, 0xA4, 0xA2,
|
||||
0x95, 0x93, 0x94, 0x6F, 0xA3, 0x97, 0x96, 0x81,
|
||||
0x2B, 0xF8, 0x9B, 0x9C, 0x15, 0xF9, 0x14, 0xE1,
|
||||
0x52, 0x43, 0x7E, 0x27, 0x22, 0xD8, 0x92, 0x30,
|
||||
0xEC, 0xF1, 0xF3, 0xF2, 0x9D, 0xE6, 0xEB, 0xE4,
|
||||
0xE3, 0xE3, 0xF4, 0xA6, 0xA7, 0xEA, 0x91, 0xED,
|
||||
0xA8, 0xAD, 0xAA, 0xFB, 0x9F, 0xF7, 0x1E, 0xAE,
|
||||
0xAF, 0x5F, 0x20, 0x41, 0x41, 0x4F, 0x99, 0x94,
|
||||
0x2D, 0xC4, 0x22, 0x22, 0x60, 0x27, 0xF6, 0x04,
|
||||
0x98, 0x59, 0x2F, 0xE8, 0x3C, 0x3E, 0x79, 0x59,
|
||||
0x2B, 0xFA, 0x2C, 0x22, 0x70, 0x41, 0x45, 0x41,
|
||||
0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F,
|
||||
0x20, 0x4F, 0x55, 0x55, 0x55, 0x2C, 0x5E, 0x7E,
|
||||
0x2D, 0x60, 0xF8, 0xF8, 0x2C, 0x22, 0x2C, 0x27
|
||||
};
|
||||
|
||||
|
||||
static char *geos2ibm(char *out, char *in, size_t insize)
|
||||
{
|
||||
char *saved = out;
|
||||
for ( int i=0; i < insize; i++ )
|
||||
{
|
||||
uchar c = *in++;
|
||||
if ( !c )
|
||||
break;
|
||||
if ( c & 0x80 )
|
||||
c = _GeosXlapp[c & 0x7F];
|
||||
*out++ = c;
|
||||
}
|
||||
*out = '\0';
|
||||
return saved;
|
||||
}
|
||||
|
||||
|
||||
795
idasdk76/ldr/geos/geos.cpp
Normal file
795
idasdk76/ldr/geos/geos.cpp
Normal file
@@ -0,0 +1,795 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2000 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "geos2.h"
|
||||
#include "common.cpp"
|
||||
#include <struct.hpp>
|
||||
#include <enum.hpp>
|
||||
#include <typeinf.hpp>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int create_seg(
|
||||
ea_t base,
|
||||
ea_t start,
|
||||
ea_t end,
|
||||
const char *name,
|
||||
const char *sclass)
|
||||
{
|
||||
if ( start != BADADDR && end < start )
|
||||
return 0;
|
||||
segment_t s;
|
||||
s.sel = setup_selector(base);
|
||||
s.start_ea = start;
|
||||
s.end_ea = end;
|
||||
s.align = saRelByte;
|
||||
s.comb = (sclass != NULL && strcmp(sclass,"STACK") == 0) ? scStack : scPub;
|
||||
s.bitness = 0;
|
||||
return add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
union
|
||||
{
|
||||
GEOSheader h1;
|
||||
GEOS2header h2;
|
||||
} h;
|
||||
qlseek(li, 0);
|
||||
if ( qlread(li, &h, sizeof(h)) != sizeof(h) )
|
||||
return 0;
|
||||
|
||||
qoff64_t apppos;
|
||||
int version;
|
||||
if ( h.h1.ID == GEOS_ID && h.h1.fclass == 0 )
|
||||
{
|
||||
apppos = 0xC8;
|
||||
version = 1;
|
||||
}
|
||||
else if ( h.h2.ID == GEOS2_ID && h.h2.fclass == 1 )
|
||||
{
|
||||
apppos = sizeof(GEOS2header);
|
||||
version = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GEOSappheader ah;
|
||||
qlseek(li, apppos, SEEK_SET);
|
||||
if ( qlread(li, &ah, sizeof(ah)) != sizeof(ah) )
|
||||
return 0;
|
||||
const char *stype;
|
||||
switch ( ah.type )
|
||||
{
|
||||
case 1: stype = "Application"; break;
|
||||
case 2: stype = "Library"; break;
|
||||
case 3: stype = "Driver"; break;
|
||||
default: stype = "Unknown type";break;
|
||||
}
|
||||
fileformatname->sprnt("GEOS%d %s", version, stype);
|
||||
*processor = "metapc";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static ea_t get_segea(const GEOSappheader &ah, const uint32 *segea, uint16 s)
|
||||
{
|
||||
if ( s >= ah.numseg )
|
||||
{
|
||||
ask_for_feedback("Bad segment number %d", s);
|
||||
return BADADDR;
|
||||
}
|
||||
return segea[s] == uint32(BADADDR) ? BADADDR : segea[s];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static netnode get_node(const GEOSappheader &ah, const netnode *modnode, uint16 libn)
|
||||
{
|
||||
if ( libn >= ah.numlib )
|
||||
{
|
||||
ask_for_feedback("Bad library number %d", libn);
|
||||
return BADNODE;
|
||||
}
|
||||
return modnode[libn];
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static tid_t get_class_struct_flags_enum()
|
||||
{
|
||||
static const char enum_name[] = "ClassFlags";
|
||||
enum_t id = get_enum(enum_name);
|
||||
if ( id != BADNODE )
|
||||
return id;
|
||||
id = add_enum(-1, enum_name, hex_flag());
|
||||
set_enum_bf(id, true);
|
||||
add_enum_member(id, "CLASSF_HAS_DEFAULT", (1<<0), (1<<0));
|
||||
add_enum_member(id, "CLASSF_MASTER_CLASS", (1<<1), (1<<1));
|
||||
add_enum_member(id, "CLASSF_VARIANT_CLASS", (1<<2), (1<<2));
|
||||
add_enum_member(id, "CLASSF_DISCARD_ON_SAVE", (1<<3), (1<<3));
|
||||
add_enum_member(id, "CLASSF_NEVER_SAVED", (1<<4), (1<<4));
|
||||
add_enum_member(id, "CLASSF_HAS_RELOC", (1<<5), (1<<5));
|
||||
add_enum_member(id, "CLASSF_C_HANDLERS", (1<<6), (1<<6));
|
||||
return id;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
#if 0
|
||||
static void declare_parameter_types(ea_t ea, int count)
|
||||
{
|
||||
static const char class_name[] = "CMethodDef";
|
||||
struc_t *sptr = get_struc(get_struc_id(class_name));
|
||||
if ( sptr == NULL )
|
||||
{
|
||||
sptr = get_struc(add_struc(-1, class_name));
|
||||
if ( sptr == NULL )
|
||||
return;
|
||||
add_struc_member(sptr, "methodParameterDef", -1, word_flag(), NULL, 2);
|
||||
add_struc_member(sptr, "handlerTypeDef", -1, byte_flag(), NULL, 1);
|
||||
}
|
||||
size_t size = get_struc_size(sptr);
|
||||
create_struct(ea, size*count, sptr->id);
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void declare_class(ea_t ea, const char *entryname)
|
||||
{
|
||||
static const char class_name[] = "ClassStruct";
|
||||
struc_t *sptr = get_struc(get_struc_id(class_name));
|
||||
if ( sptr == NULL )
|
||||
{
|
||||
sptr = get_struc(add_struc(BADADDR, class_name));
|
||||
if ( sptr == NULL )
|
||||
return;
|
||||
opinfo_t mt;
|
||||
mt.ri.flags = REF_OFF32;
|
||||
mt.ri.target = BADADDR;
|
||||
mt.ri.base = 0;
|
||||
mt.ri.tdelta = 0;
|
||||
add_struc_member(sptr, "superClass", BADADDR, off_flag()|dword_flag(), &mt, 4);
|
||||
add_struc_member(sptr, "masterOffset", BADADDR, word_flag(), NULL, 2);
|
||||
add_struc_member(sptr, "methodCount", BADADDR, dec_flag()|word_flag(), NULL, 2);
|
||||
add_struc_member(sptr, "instanceSize", BADADDR, dec_flag()|word_flag(), NULL, 2);
|
||||
add_struc_member(sptr, "vdRelocTable", BADADDR, word_flag(), NULL, 2);
|
||||
add_struc_member(sptr, "relocTable", BADADDR, word_flag(), NULL, 2);
|
||||
mt.ec.tid = get_class_struct_flags_enum();
|
||||
mt.ec.serial = 0;
|
||||
add_struc_member(sptr, "flags", BADADDR, enum_flag()|byte_flag(), &mt, 1);
|
||||
add_struc_member(sptr, "masterMethods",BADADDR, byte_flag(), NULL, 1);
|
||||
}
|
||||
asize_t size = get_struc_size(sptr);
|
||||
create_struct(ea, size, sptr->id);
|
||||
|
||||
segment_t *s = getseg(ea);
|
||||
if ( s == NULL )
|
||||
return;
|
||||
int count = get_word(ea+6);
|
||||
// bool c_handlers = get_byte(ea+14) & (1<<6);
|
||||
ea += size;
|
||||
if ( ea+2*count >= s->end_ea )
|
||||
return;
|
||||
ea_t messages = ea;
|
||||
create_word(ea, count*2);
|
||||
op_dec(ea, 0);
|
||||
ea += 2*count;
|
||||
if ( ea+4*count > s->end_ea )
|
||||
return;
|
||||
create_dword(ea, count*4);
|
||||
op_plain_offset(ea, 0, 0);
|
||||
for ( int i=0; i < count; i++ )
|
||||
{
|
||||
ea_t idx = ea + 4*i;
|
||||
ea_t pea = to_ea(get_word(idx+2), get_word(idx));
|
||||
auto_make_proc(pea);
|
||||
char name[MAXSTR];
|
||||
qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i));
|
||||
add_entry(pea, pea, name, true, AEF_IDBENC);
|
||||
}
|
||||
// commented out because it doesn't work properly
|
||||
// see geoplan.geo, entry number 1 for example
|
||||
// if ( c_handlers )
|
||||
// declare_parameter_types(ea+count*4, count);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void describe_app(const GEOSappheader &ah, const uint32 *segea)
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
char *end = buf + sizeof(buf);
|
||||
char *ptr = buf + qsnprintf(buf, sizeof(buf), "Pgm attrs :");
|
||||
if ( ah.attr & GA_PROCESS ) APPEND(ptr, end, " GA_PROCESS");
|
||||
if ( ah.attr & GA_LIBRARY ) APPEND(ptr, end, " GA_LIBRARY");
|
||||
if ( ah.attr & GA_DRIVER ) APPEND(ptr, end, " GA_DRIVER");
|
||||
if ( ah.attr & GA_KEEP_FILE_OPEN ) APPEND(ptr, end, " GA_KEEP_FILE_OPEN");
|
||||
if ( ah.attr & GA_SYSTEM ) APPEND(ptr, end, " GA_SYSTEM");
|
||||
if ( ah.attr & GA_MULTI_LAUNCHABLE ) APPEND(ptr, end, " GA_MULTI_LAUNCHABLE");
|
||||
if ( ah.attr & GA_APPLICATION ) APPEND(ptr, end, " GA_APPLICATION");
|
||||
if ( ah.attr & GA_DRIVER_INITIALIZED ) APPEND(ptr, end, " GA_DRIVER_INITIALIZED");
|
||||
if ( ah.attr & GA_LIBRARY_INITIALIZED ) APPEND(ptr, end, " GA_LIBRARY_INITIALIZED");
|
||||
if ( ah.attr & GA_GEODE_INITIALIZED ) APPEND(ptr, end, " GA_GEODE_INITIALIZED");
|
||||
if ( ah.attr & GA_USES_COPROC ) APPEND(ptr, end, " GA_USES_COPROC");
|
||||
if ( ah.attr & GA_REQUIRES_COPROC ) APPEND(ptr, end, " GA_REQUIRES_COPROC");
|
||||
if ( ah.attr & GA_HAS_GENERAL_CONSUMER_MODE ) APPEND(ptr, end, " GA_HAS_GENERAL_CONSUMER_MODE");
|
||||
if ( ah.attr & GA_ENTRY_POINTS_IN_C ) APPEND(ptr, end, " GA_ENTRY_POINTS_IN_C");
|
||||
add_pgm_cmt("%s", buf);
|
||||
|
||||
if ( ah.attr & GA_PROCESS )
|
||||
{
|
||||
ea_t entry = get_segea(ah, segea, ah.classptr_seg) + ah.classptr_ofs;
|
||||
set_name(entry, "ProcessClass", SN_NOCHECK|SN_NOWARN);
|
||||
declare_class(entry, "ProcessClass");
|
||||
// inf_set_start_cs(get_segea(ah,segea,ah.classptr_seg) >> 4);
|
||||
// inf_set_start_ip (ah.classptr_ofs);
|
||||
entry = get_segea(ah, segea, ah.tokenres_seg) + ah.tokenres_item;
|
||||
set_name(entry, "ApplicationObject");
|
||||
add_pgm_cmt("ProcessClass: %d:%04X", ah.classptr_seg, ah.classptr_ofs);
|
||||
add_pgm_cmt("App object : %d:%04X", ah.tokenres_seg, ah.tokenres_item);
|
||||
}
|
||||
if ( ah.attr & GA_LIBRARY && ah.initseg != 0 )
|
||||
{
|
||||
inf_set_start_cs(get_segea(ah, segea, ah.initseg) >> 4);
|
||||
inf_set_start_ip(ah.initofs);
|
||||
add_pgm_cmt("Library init: %d:%04X", ah.initseg, ah.initofs);
|
||||
}
|
||||
if ( ah.attr & GA_DRIVER && ah.startseg != 0 )
|
||||
{
|
||||
ea_t entry = get_segea(ah, segea, ah.startseg) + ah.startofs;
|
||||
set_name(entry, "DriverTable");
|
||||
// inf_set_start_cs(get_segea(ah, segea, ah.startseg) >> 4);
|
||||
// inf_set_start_ip (ah.startofs);
|
||||
add_pgm_cmt("Driver Table: %d:%04X", ah.startseg, ah.startofs);
|
||||
// add_jmplist(ah.startseg,ah.startofs,4,4);
|
||||
// Add entry point as "jmplist"
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void bad_lib_reloc(int i, uint16 off)
|
||||
{
|
||||
ask_for_feedback("Strange library relocation at %d:%04X", i, off);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create_fixup(ea_t ea, fixup_data_t &fd, ea_t target)
|
||||
{
|
||||
segment_t *s = getseg(target);
|
||||
if ( s != NULL )
|
||||
{
|
||||
fd.sel = s->sel;
|
||||
fd.off = target - get_segm_base(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd.sel = sel_t(target >> 4);
|
||||
fd.off = target & 0xF;
|
||||
}
|
||||
fd.displacement = 0;
|
||||
fd.set(ea);
|
||||
if ( fd.get_type() == FIXUP_PTR16 )
|
||||
{
|
||||
put_word(ea, fd.off);
|
||||
put_word(ea+2, fd.sel);
|
||||
}
|
||||
else if ( fd.get_type() == FIXUP_OFF16 )
|
||||
{
|
||||
put_word(ea, fd.off);
|
||||
}
|
||||
else // SEG16
|
||||
{
|
||||
put_word(ea, fd.sel);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void apply_relocations(
|
||||
linput_t *li,
|
||||
const GEOSappheader &ah,
|
||||
const netnode *modnode,
|
||||
const uint16 *seglen,
|
||||
const int32 *segpos,
|
||||
const uint16 *segfix,
|
||||
const uint32 *segea)
|
||||
{
|
||||
// apply relocation information
|
||||
for ( int i=0; i < ah.numseg; i++ )
|
||||
{
|
||||
if ( segfix[i] == 0 )
|
||||
continue;
|
||||
GEOSfixup *fix = (GEOSfixup *)qalloc(segfix[i]);
|
||||
if ( fix == NULL )
|
||||
nomem("fix");
|
||||
qlseek(li, segpos[i]+((seglen[i]+0xF)&~0xF));
|
||||
lread(li, fix, segfix[i]);
|
||||
int n = segfix[i]/sizeof(GEOSfixup);
|
||||
sel_t oldsel = BADSEL;
|
||||
sel_t oldoff = BADSEL;
|
||||
ea_t oldea = BADADDR;
|
||||
for ( int j=0; j < n; j++ )
|
||||
{
|
||||
ea_t ea = get_segea(ah, segea, (uint16)i) + fix[j].ofs;
|
||||
int ftype = fix[j].type & 0xF0;
|
||||
if ( ftype != 0x10 && ftype != 0x20 )
|
||||
ask_for_feedback("Unknown fixup type %02X", ftype);
|
||||
netnode libnode = BADNODE;
|
||||
if ( ftype == 0x10 )
|
||||
libnode = get_node(ah, modnode, fix[j].type>>8);
|
||||
uint16 w1 = get_word(ea);
|
||||
ea_t target = BADADDR;
|
||||
fixup_data_t fd(FIXUP_SEG16);
|
||||
switch ( fix[j].type & 0x0F )
|
||||
{
|
||||
case 0x0: case 0x4:
|
||||
fd.set_type_and_flags(FIXUP_PTR16);
|
||||
if ( ftype == 0x20 ) // program
|
||||
target = get_segea(ah, segea, w1) + get_word(ea+2);
|
||||
else // library
|
||||
{
|
||||
target = node2ea(libnode.altval(w1+1));
|
||||
fd.set_extdef();
|
||||
}
|
||||
break;
|
||||
case 0x1: // off
|
||||
if ( ftype == 0x20 ) // program
|
||||
{
|
||||
ask_for_feedback("Program offset relocation encountered");
|
||||
continue;
|
||||
}
|
||||
oldoff = w1;
|
||||
if ( oldsel != BADSEL )
|
||||
{
|
||||
LIB_PTR:
|
||||
target = node2ea(libnode.altval(oldoff+1));
|
||||
if ( oldea == ea+2 )
|
||||
{
|
||||
fd.set_type_and_flags(FIXUP_PTR16, FIXUPF_EXTDEF);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd.set_type_and_flags(FIXUP_SEG16, FIXUPF_EXTDEF);
|
||||
create_fixup(oldea, fd, target);
|
||||
fd.set_type_and_flags(FIXUP_OFF16, FIXUPF_EXTDEF);
|
||||
}
|
||||
oldsel = BADSEL;
|
||||
oldoff = BADSEL;
|
||||
oldea = BADSEL;
|
||||
break;
|
||||
}
|
||||
oldea = ea;
|
||||
continue;
|
||||
case 0x2: case 0x3:
|
||||
if ( ftype == 0x20 ) // program
|
||||
target = get_segea(ah, segea, w1);
|
||||
else
|
||||
{
|
||||
oldsel = w1;
|
||||
if ( oldoff != BADSEL )
|
||||
{
|
||||
ea_t tmp = ea;
|
||||
ea = oldea;
|
||||
oldea = tmp;
|
||||
goto LIB_PTR;
|
||||
}
|
||||
oldea = ea;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ask_for_feedback("Unknown relocation type %02X", fix[j].type);
|
||||
}
|
||||
create_fixup(ea, fd, target);
|
||||
}
|
||||
qfree(fix);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void find_imports_in_relocations(
|
||||
linput_t *li,
|
||||
const GEOSappheader &ah,
|
||||
const netnode *modnode,
|
||||
const uint16 *seglen,
|
||||
const int32 *segpos,
|
||||
const uint16 *segfix)
|
||||
{
|
||||
for ( int i=0; i < ah.numseg; i++ )
|
||||
{
|
||||
if ( segfix[i] == 0 )
|
||||
continue;
|
||||
GEOSfixup *fix = (GEOSfixup *)qalloc(segfix[i]);
|
||||
if ( fix == NULL )
|
||||
nomem("fix");
|
||||
qlseek(li, segpos[i]+((seglen[i]+0xF)&~0xF));
|
||||
lread(li, fix, segfix[i]);
|
||||
// i don't understand why this should be done
|
||||
// besides, if we uncomment it, the library fixups are
|
||||
// not handled properly
|
||||
// if ( fix[0].ofs == 0 )
|
||||
// fix[0].ofs = 0xFFFF;
|
||||
int num = segfix[i]/sizeof(GEOSfixup);
|
||||
sel_t oldseg = BADSEL;
|
||||
sel_t oldoff = BADSEL;
|
||||
sel_t oldlib = BADSEL;
|
||||
for ( int j=0; j < num; j++ )
|
||||
{
|
||||
if ( fix[j].ofs == 0xFFFF )
|
||||
continue;
|
||||
if ( (fix[j].type & 0xF0) != 0x10 )
|
||||
continue; // only library!
|
||||
int libn = fix[j].type>>8;
|
||||
if ( libn >= ah.numlib )
|
||||
{
|
||||
ask_for_feedback("Illegal library number in relocations");
|
||||
continue;
|
||||
}
|
||||
netnode n = modnode[libn];
|
||||
uint16 ofs = fix[j].ofs;
|
||||
qlseek(li, segpos[i]+ofs);
|
||||
uint16 w1;
|
||||
lread(li, &w1, sizeof(w1));
|
||||
switch ( fix[j].type & 0x0F )
|
||||
{
|
||||
case 0x0: case 0x4: // exported entry
|
||||
n.altset(w1+1, 1);
|
||||
oldseg = BADSEL;
|
||||
oldoff = BADSEL;
|
||||
oldlib = BADSEL;
|
||||
break;
|
||||
case 0x1: // off
|
||||
if ( oldseg != BADSEL )
|
||||
{
|
||||
if ( libn != oldlib || oldseg != w1 )
|
||||
bad_lib_reloc(i, ofs);
|
||||
n.altset(w1+1, 1);
|
||||
oldseg = BADSEL;
|
||||
break;
|
||||
}
|
||||
oldoff = w1;
|
||||
oldlib = libn;
|
||||
break;
|
||||
case 0x2: case 0x3: // seg #
|
||||
if ( oldoff != BADSEL )
|
||||
{
|
||||
if ( libn != oldlib || oldoff != w1 )
|
||||
bad_lib_reloc(i, ofs);
|
||||
n.altset(w1+1, 1);
|
||||
oldoff = BADSEL;
|
||||
break;
|
||||
}
|
||||
oldseg = w1;
|
||||
oldlib = libn;
|
||||
break;
|
||||
default:
|
||||
ask_for_feedback("Unknown relocation type %02X", fix[j].type);
|
||||
}
|
||||
}
|
||||
if ( oldseg != BADSEL && oldoff != BADSEL )
|
||||
ask_for_feedback("Some library relocations are strange");
|
||||
qfree(fix);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create_extern_segments(
|
||||
const GEOSappheader &ah,
|
||||
const GEOSliblist *lib,
|
||||
const netnode *modnode)
|
||||
{
|
||||
inf_set_specsegs(inf_is_64bit() ? 8 : 4);
|
||||
for ( int i=0; i < ah.numlib; i++ )
|
||||
{
|
||||
char libname[8+1];
|
||||
qstrncpy(libname, lib[i].name, sizeof(libname));
|
||||
trim(libname);
|
||||
netnode n = modnode[i];
|
||||
uval_t x;
|
||||
int nimps = 0;
|
||||
for ( x=n.altfirst(); x != BADNODE; x=n.altnext(x) )
|
||||
nimps++;
|
||||
if ( nimps == 0 )
|
||||
continue;
|
||||
|
||||
ea_t ea = free_chunk(inf_get_max_ea(), nimps*4, -15);
|
||||
ea_t end = ea + nimps*4;
|
||||
create_seg(ea>>4, ea, end, libname, "XTRN");
|
||||
for ( x=n.altfirst(); x != BADNODE; x=n.altnext(x),ea+=4 )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
qsnprintf(buf, sizeof(buf), "%s_%u", libname, uint16(x)-1);
|
||||
put_dword(ea, 0xCB);
|
||||
create_insn(ea);
|
||||
force_name(ea, buf, SN_IDBENC);
|
||||
nodeidx_t ndx = ea2node(ea);
|
||||
n.altset(x, ndx);
|
||||
}
|
||||
import_module(libname, NULL /*windir*/, n, NULL, "geos");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create_exports(
|
||||
const GEOSappheader &ah,
|
||||
const GEOSexplist *explist,
|
||||
const uint32 *segea,
|
||||
const char *modname)
|
||||
{
|
||||
int i;
|
||||
netnode n;
|
||||
n.create();
|
||||
for ( i=0; i < ah.numexp; i++ )
|
||||
{
|
||||
ea_t ea = get_segea(ah, segea, explist[i].seg) + explist[i].ofs;
|
||||
add_extra_cmt(ea, true, "Exported entry %d", i);
|
||||
nodeidx_t ndx = ea2node(ea);
|
||||
n.altset(i+1, ndx);
|
||||
}
|
||||
import_module(modname, NULL /*windir*/, n, NULL, "geos");
|
||||
for ( i=0; i < ah.numexp; i++ )
|
||||
{
|
||||
ea_t ea = get_segea(ah, segea, explist[i].seg) + explist[i].ofs;
|
||||
qstring name;
|
||||
if ( get_name(&name, ea, GN_NOT_DUMMY) <= 0 )
|
||||
name.sprnt("%s_%d", modname, i);
|
||||
bool makecode = segtype(ea) == SEG_CODE;
|
||||
add_entry(i, ea, name.begin(), makecode, AEF_IDBENC);
|
||||
if ( !makecode )
|
||||
declare_class(ea, name.begin());
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void load_application(linput_t *li, int32 fpos, int32 fdelta)
|
||||
{
|
||||
GEOSappheader ah;
|
||||
|
||||
qlseek(li, fpos);
|
||||
lread(li, &ah, sizeof(ah));
|
||||
|
||||
// build our name
|
||||
char modname[sizeof(ah.name)+1];
|
||||
qstrncpy(modname, ah.name, sizeof(ah.name));
|
||||
trim(modname);
|
||||
|
||||
// read in library information
|
||||
GEOSliblist *lib = NULL;
|
||||
netnode *modnode = NULL;
|
||||
validate_array_count(li, &ah.numlib, sizeof(GEOSliblist), "The library count");
|
||||
if ( ah.numlib != 0 )
|
||||
{
|
||||
lib = qalloc_array<GEOSliblist>(ah.numlib);
|
||||
if ( lib == NULL )
|
||||
nomem("libs");
|
||||
lread(li, lib, ah.numlib*sizeof(GEOSliblist));
|
||||
modnode = qalloc_array<netnode>(ah.numlib);
|
||||
if ( modnode == NULL )
|
||||
nomem("libnode");
|
||||
for ( int i=0; i < ah.numlib; i++ )
|
||||
{
|
||||
char libname[8+1];
|
||||
qstrncpy(libname, lib[i].name, sizeof(libname));
|
||||
trim(libname);
|
||||
char buf[20];
|
||||
qsnprintf(buf, sizeof(buf), "$lib %.8s", libname);
|
||||
modnode[i].create(buf);
|
||||
}
|
||||
}
|
||||
|
||||
// read in export information
|
||||
GEOSexplist *explist = NULL;
|
||||
validate_array_count(li, &ah.numexp, sizeof(GEOSexplist), "Number of exports");
|
||||
if ( ah.numexp != 0 )
|
||||
{
|
||||
explist = qalloc_array<GEOSexplist>(ah.numexp);
|
||||
if ( explist == NULL )
|
||||
nomem("exp");
|
||||
lread(li, explist, ah.numexp*sizeof(GEOSexplist));
|
||||
}
|
||||
|
||||
// read in segment information
|
||||
void *segd = NULL;
|
||||
uint16 *seglen = NULL;
|
||||
int32 *segpos = NULL;
|
||||
uint16 *segfix = NULL;
|
||||
uint16 *segflg;
|
||||
sel_t ds_sel = BADSEL;
|
||||
uint32 *segea = NULL;
|
||||
validate_array_count(li, &ah.numseg, 14, "Number of segments");
|
||||
if ( ah.numseg != 0 )
|
||||
{
|
||||
if ( !is_mul_ok<ushort>(ah.numseg, 14) )
|
||||
NOMEM:
|
||||
nomem("geos_segments");
|
||||
segd = qalloc(ah.numseg*14);
|
||||
if ( segd == NULL )
|
||||
goto NOMEM;
|
||||
lread(li, segd, ah.numseg*10);
|
||||
seglen = (uint16 *)segd;
|
||||
segpos = (int32 *)(seglen + ah.numseg);
|
||||
segfix = (uint16 *)(segpos + ah.numseg);
|
||||
segflg = (uint16 *)(segfix + ah.numseg);
|
||||
segea = (uint32 *)(segflg + ah.numseg);
|
||||
ea_t ea = to_ea(inf_get_baseaddr(), 0);
|
||||
for ( int i=0; i < ah.numseg; i++ )
|
||||
{
|
||||
uint16 f = segflg[i];
|
||||
segpos[i] += fdelta;
|
||||
|
||||
segea[i] = uint32(BADADDR);
|
||||
if ( seglen[i] == 0 )
|
||||
continue;
|
||||
size_t bss_size = 0;
|
||||
// if this is the data segment, increase its size by stacksize.
|
||||
// i'm not aware of a reliable way to find it, so use heuristics
|
||||
bool found_data_segment = false;
|
||||
if ( ds_sel == BADSEL
|
||||
&& (f & (HF_READ_ONLY|HF_SHARABLE|HF_CODE)) == 0
|
||||
&& (f & HF_FIXED) != 0 )
|
||||
{
|
||||
found_data_segment = true;
|
||||
bss_size = ah.stacksize;
|
||||
}
|
||||
ea = free_chunk(ea, bss_size + seglen[i], -15);
|
||||
ea_t endea = ea + seglen[i] + bss_size;
|
||||
if ( (f & HF_ZERO_INIT) == 0 )
|
||||
file2base(li, segpos[i], ea, endea - bss_size, FILEREG_PATCHABLE);
|
||||
create_seg(ea>>4, ea, endea, NULL, (f & HF_CODE) ? "CODE" : "DATA");
|
||||
|
||||
if ( found_data_segment )
|
||||
ds_sel = find_selector(ea>>4);
|
||||
|
||||
char buf[MAXSTR];
|
||||
char *end = buf + sizeof(buf);
|
||||
char *ptr = buf + qsnprintf(buf, sizeof(buf), "Segm attrs :");
|
||||
if ( f & HF_ZERO_INIT ) APPEND(ptr, end, " ZEROINIT");
|
||||
if ( f & HF_LOCK ) APPEND(ptr, end, " LOCK");
|
||||
if ( f & HF_NO_ERR ) APPEND(ptr, end, " NO_ERR");
|
||||
if ( f & HF_UI ) APPEND(ptr, end, " UI");
|
||||
if ( f & HF_READ_ONLY ) APPEND(ptr, end, " RONLY");
|
||||
if ( f & HF_OBJECT_RESOURCE ) APPEND(ptr, end, " OBJ_RES");
|
||||
if ( f & HF_CODE ) APPEND(ptr, end, " CODE");
|
||||
if ( f & HF_CONFORMING ) APPEND(ptr, end, " CONFORMING");
|
||||
if ( f & HF_FIXED ) APPEND(ptr, end, " FIXED");
|
||||
if ( f & HF_SHARABLE ) APPEND(ptr, end, " SHARABLE");
|
||||
if ( f & HF_DISCARDABLE ) APPEND(ptr, end, " DISCARDABLE");
|
||||
if ( f & HF_SWAPABLE ) APPEND(ptr, end, " SWAPABLE");
|
||||
if ( f & HF_LMEM ) APPEND(ptr, end, " LMEM");
|
||||
if ( f & HF_DEBUG ) APPEND(ptr, end, " DEBUG");
|
||||
if ( f & HF_DISCARDED ) APPEND(ptr, end, " DISCARDED");
|
||||
if ( f & HF_SWAPPED ) APPEND(ptr, end, " SWAPPED");
|
||||
add_extra_cmt(ea, true, "%s", buf);
|
||||
|
||||
segea[i] = (uint32)ea;
|
||||
ea = endea;
|
||||
}
|
||||
}
|
||||
|
||||
find_imports_in_relocations(li, ah, modnode, seglen, segpos, segfix);
|
||||
create_extern_segments(ah, lib, modnode);
|
||||
set_default_dataseg(ds_sel);
|
||||
|
||||
if ( !qgetenv("IDA_NORELOC") )
|
||||
apply_relocations(li, ah, modnode, seglen, segpos, segfix, segea);
|
||||
|
||||
create_exports(ah, explist, segea, modname);
|
||||
|
||||
describe_app(ah, segea);
|
||||
qfree(lib);
|
||||
qfree(modnode);
|
||||
qfree(explist);
|
||||
qfree(segd);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void show_geos1(GEOSheader &h)
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
add_pgm_cmt("Name : %s", geos2ibm(buf, h.name, sizeof(h.name)));
|
||||
add_pgm_cmt("Token : %s", token2str(buf, sizeof(buf), h.token));
|
||||
add_pgm_cmt("Creator : %s", token2str(buf, sizeof(buf), h.appl));
|
||||
add_pgm_cmt("Release : %u.%u.%u.%u",
|
||||
h.release.versmaj,
|
||||
h.release.versmin,
|
||||
h.release.revmaj,
|
||||
h.release.revmin);
|
||||
add_pgm_cmt("Protocol : %u.%03u",
|
||||
h.protocol.vers,
|
||||
h.protocol.rev);
|
||||
add_pgm_cmt("Flags : %04X", h.flags);
|
||||
add_pgm_cmt("User info : %s", geos2ibm(buf, h.info, sizeof(h.info)));
|
||||
add_pgm_cmt("Copyright : %s", geos2ibm(buf, h._copyright, sizeof(h._copyright)));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void show_geos2(GEOS2header &h)
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
add_pgm_cmt("Name : %s", geos2ibm(buf, h.name, sizeof(h.name)));
|
||||
add_pgm_cmt("Token : %s", token2str(buf, sizeof(buf), h.token));
|
||||
add_pgm_cmt("Creator : %s", token2str(buf, sizeof(buf), h.appl));
|
||||
add_pgm_cmt("Release : %u.%u.%u.%u",
|
||||
h.release.versmaj,
|
||||
h.release.versmin,
|
||||
h.release.revmaj,
|
||||
h.release.revmin);
|
||||
add_pgm_cmt("Protocol : %u.%03u",
|
||||
h.protocol.vers,
|
||||
h.protocol.rev);
|
||||
add_pgm_cmt("Flags : %04X", h.flags);
|
||||
add_pgm_cmt("Password : %.*s", int(sizeof(h.password)), h.password);
|
||||
add_pgm_cmt("User info : %s", geos2ibm(buf, h.info, sizeof(h.info)));
|
||||
add_pgm_cmt("Copyright : %s", geos2ibm(buf, h._copyright, sizeof(h._copyright)));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, uint16 /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
set_processor_type("metapc", SETPROC_LOADER);
|
||||
|
||||
union
|
||||
{
|
||||
GEOSheader h1;
|
||||
GEOS2header h2;
|
||||
} h;
|
||||
qlseek(li, 0);
|
||||
lread(li, &h, sizeof(h));
|
||||
|
||||
int32 apppos;
|
||||
int32 fdelta;
|
||||
if ( h.h1.ID == GEOS_ID )
|
||||
{
|
||||
apppos = 0xC8;
|
||||
fdelta = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
apppos = sizeof(GEOS2header);
|
||||
fdelta = apppos;
|
||||
}
|
||||
|
||||
load_application(li, apppos, fdelta);
|
||||
|
||||
create_filename_cmt();
|
||||
if ( h.h1.ID == GEOS_ID )
|
||||
show_geos1(h.h1);
|
||||
else
|
||||
show_geos2(h.h2);
|
||||
|
||||
inf_set_cc_cm(inf_get_cc_cm() | C_PC_LARGE);
|
||||
add_til("geos", ADDTIL_DEFAULT);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
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,
|
||||
};
|
||||
173
idasdk76/ldr/geos/geos.h
Normal file
173
idasdk76/ldr/geos/geos.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
GEOS.H
|
||||
by Marcus Groeber 1992-95
|
||||
Include file for the PC/GEOS file format
|
||||
|
||||
20.06.00: Modified by Ilfak Guilfanov <ig@datarescue.com>
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(_GEOS_H)
|
||||
#define _GEOS_H
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define GEOS_TOKENLEN 4
|
||||
struct GEOStoken
|
||||
{ /*** ID for file types/icons */
|
||||
char str[GEOS_TOKENLEN]; // 4 byte string
|
||||
ushort num; // additional id number (?)
|
||||
};
|
||||
|
||||
struct GEOSprotocol
|
||||
{ /*** Protocol/version number */
|
||||
ushort vers; // protocol
|
||||
ushort rev; // sub revision
|
||||
};
|
||||
|
||||
struct GEOSrelease
|
||||
{ /*** "Release" */
|
||||
ushort versmaj,versmin; // "release" x.y
|
||||
ushort revmaj,revmin; // value "a-b" behind "release"
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* GEOS standard file header (all file types) *
|
||||
******************************************************************************/
|
||||
#define GEOS_LONGNAME 36 // length of filename
|
||||
#define GEOS_INFO 100 // length of user file info
|
||||
|
||||
#define GEOS_ID 0x53CF45C7 // GEOS file identification "magic"
|
||||
|
||||
struct GEOSheader
|
||||
{ /*** Standard-Dateikof */
|
||||
int32 ID; // GEOS id magic: C7 45 CF 53
|
||||
ushort fclass; // 00=applciation, 01=VM file
|
||||
ushort flags; // flags ??? (always seen 0000h)
|
||||
GEOSrelease release; // "release"
|
||||
GEOSprotocol protocol; // protocol/version
|
||||
GEOStoken token; // file type/icon
|
||||
GEOStoken appl; // "token" of creator application
|
||||
char name[GEOS_LONGNAME]; // long filename
|
||||
char info[GEOS_INFO]; // user file info
|
||||
char _copyright[24]; // original files: Copyright notice
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* GEOS program files ("geodes") *
|
||||
******************************************************************************/
|
||||
#define GEOS_FNAME 8 // Length of internale filename/ext
|
||||
#define GEOS_FEXT 4
|
||||
|
||||
struct GEOSappheader
|
||||
{ /*** Additional geode file header */
|
||||
ushort _attr; // attribute (see below)
|
||||
#define GA_PROCESS 0x8000
|
||||
#define GA_LIBRARY 0x4000
|
||||
#define GA_DRIVER 0x2000
|
||||
#define GA_KEEP_FILE_OPEN 0x1000
|
||||
#define GA_SYSTEM 0x0800
|
||||
#define GA_MULTI_LAUNCHABLE 0x0400
|
||||
#define GA_APPLICATION 0x0200
|
||||
#define GA_DRIVER_INITIALIZED 0x0100
|
||||
#define GA_LIBRARY_INITIALIZED 0x0080
|
||||
#define GA_GEODE_INITIALIZED 0x0040
|
||||
#define GA_USES_COPROC 0x0020
|
||||
#define GA_REQUIRES_COPROC 0x0010
|
||||
#define GA_HAS_GENERAL_CONSUMER_MODE 0x0008
|
||||
#define GA_ENTRY_POINTS_IN_C 0x0004
|
||||
ushort _type; // program type (see below)
|
||||
GEOSprotocol kernelprot; // expected kernel protocoll
|
||||
ushort resourceCount; // number of segments
|
||||
ushort importLibraryCount; // number of included libraries
|
||||
ushort exportEntryCount; // number of exported locations
|
||||
ushort stacksize; // default stack size (or udataSize)
|
||||
ushort classptr_ofs; // if application: segment/offset of ???
|
||||
ushort classptr_seg;
|
||||
ushort tokenres_item; // if application: segment/item of
|
||||
ushort tokenres_seg; // ressource with application token
|
||||
char _x21[2];
|
||||
|
||||
// GEOS2 header start here:
|
||||
|
||||
ushort attr; // attribute
|
||||
ushort type; // program type: 01=application
|
||||
// 02=library
|
||||
// 03=device driver
|
||||
GEOSrelease release; // "release"
|
||||
GEOSprotocol protocol; // protocol/version
|
||||
ushort timestamp; // time stamp (SWAT uniqueness)
|
||||
char name[GEOS_FNAME],ext[GEOS_FEXT]; // internal filename/ext (blank padded)
|
||||
GEOStoken token; // file type/icon
|
||||
char _x3[2];
|
||||
ushort startofs; // if driver: entry location
|
||||
ushort startseg; // " "
|
||||
ushort initofs; // if library: init location (?)
|
||||
ushort initseg; // " "
|
||||
char _x33[2];
|
||||
ushort numexp; // number of exports
|
||||
ushort numlib; // number of included libraries
|
||||
char _x4[2];
|
||||
ushort numseg; // Number of program segments
|
||||
char _x5[6];
|
||||
};
|
||||
|
||||
struct GEOSexplist
|
||||
{ /*** Base type of "exported" array */
|
||||
ushort ofs; // Routine entry location
|
||||
ushort seg; // " " "
|
||||
};
|
||||
|
||||
struct GEOSliblist
|
||||
{ /*** Base typ of library array */
|
||||
char name[GEOS_FNAME]; // library name
|
||||
ushort type; // library type: 2000h=driver
|
||||
// 4000h=library
|
||||
GEOSprotocol protocol; // required lib protocol/version
|
||||
};
|
||||
|
||||
typedef ushort GEOSseglen; /*** Base type of segment size array */
|
||||
typedef int32 GEOSsegpos; /*** Base type of segment loc array */
|
||||
typedef ushort GEOSsegfix; /*** Base type of fixup tab size ary */
|
||||
typedef ushort GEOSsegflags; /*** Base type of flag array:
|
||||
xxxx xxxx xxxx xxxxb
|
||||
*/
|
||||
|
||||
#define HF_ZERO_INIT 0x8000
|
||||
#define HF_LOCK 0x4000
|
||||
#define HF_NO_ERR 0x2000
|
||||
#define HF_UI 0x1000
|
||||
#define HF_READ_ONLY 0x0800
|
||||
#define HF_OBJECT_RESOURCE 0x0400
|
||||
#define HF_CODE 0x0200
|
||||
#define HF_CONFORMING 0x0100
|
||||
#define HF_FIXED 0x0080
|
||||
#define HF_SHARABLE 0x0040
|
||||
#define HF_DISCARDABLE 0x0020
|
||||
#define HF_SWAPABLE 0x0010
|
||||
#define HF_LMEM 0x0008
|
||||
#define HF_DEBUG 0x0004
|
||||
#define HF_DISCARDED 0x0002
|
||||
#define HF_SWAPPED 0x0001
|
||||
|
||||
struct GEOSfixup
|
||||
{ /*** Base typ of segment fixup table */
|
||||
ushort type; // Type of fixup:
|
||||
// xxxxh
|
||||
// +|||
|
||||
// | |0 = 16/16 pointer to routine #
|
||||
// | |1 = 16 offset to routine #
|
||||
// | |2 = 16 segment of routine #
|
||||
// | |3 = 16 segment
|
||||
// | |4 = 16/16 pointer (seg,ofs!)
|
||||
// | 0 = kernel
|
||||
// | 1 = library
|
||||
// | 2 = program
|
||||
// xx = if library: library ord #
|
||||
ushort ofs; // Offset relative to segment
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
60
idasdk76/ldr/geos/geos2.h
Normal file
60
idasdk76/ldr/geos/geos2.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
GEOS2.H
|
||||
by Marcus Groeber 1993-94
|
||||
Include file for the PC/GEOS 2 file format
|
||||
|
||||
20.06.00: Modified by Ilfak Guilfanov <ig@datarescue.com>
|
||||
*/
|
||||
|
||||
#ifndef GEOS2_H
|
||||
#define GEOS2_H
|
||||
|
||||
#include "geos.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/*
|
||||
* Packed time and date structures; bitfield order is compiler dependant.
|
||||
*/
|
||||
struct PackedFileDate
|
||||
{
|
||||
ushort d:5;
|
||||
ushort m:4;
|
||||
ushort y:7;
|
||||
};
|
||||
|
||||
struct PackedFileTime
|
||||
{
|
||||
ushort s_2:5;
|
||||
ushort m:6;
|
||||
ushort h:5;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* GEOS standard file header (all file types) *
|
||||
******************************************************************************/
|
||||
#define GEOS2_ID 0x53C145C7 // GEOS2 file identification "magic"
|
||||
|
||||
struct GEOS2header
|
||||
{ /*** GEOS2 standard header */
|
||||
int32 ID; // GEOS2 id magic: C7 45 CF 53
|
||||
char name[GEOS_LONGNAME]; // long filename
|
||||
ushort fclass; // geos filetype, see SDK docs
|
||||
// 1-executable
|
||||
ushort flags; // attributes
|
||||
GEOSrelease release; // "release"
|
||||
GEOSprotocol protocol; // protocol/version
|
||||
GEOStoken token; // file type/icon
|
||||
GEOStoken appl; // "token" of creator application
|
||||
char info[GEOS_INFO]; // user file info
|
||||
char _copyright[24]; // original files: Copyright notice
|
||||
char _x[8];
|
||||
PackedFileDate create_date;
|
||||
PackedFileTime create_time; // creation date/time in DOS format
|
||||
char password[8]; // password, encrypted as hex string
|
||||
char _x2[44]; // not yet decoded
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif // define GEOS2_H
|
||||
14
idasdk76/ldr/geos/makefile
Normal file
14
idasdk76/ldr/geos/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=geos
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)geos$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)enum.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)struct.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaldr.h common.cpp geos.cpp geos.h geos2.h
|
||||
624
idasdk76/ldr/hex/hex.cpp
Normal file
624
idasdk76/ldr/hex/hex.cpp
Normal file
@@ -0,0 +1,624 @@
|
||||
#define BUFFSIZE ((255+6)*2+76) // buffer to read the string
|
||||
#define MAX_BYTES 24 // Max number of bytes per line for write
|
||||
#define SEGMENTGAP (1*1024*1024) // make new segment if gap between addresses
|
||||
// is greater than this value
|
||||
#define SPARSE_GAP (256*1024) // switch to sparse storage if the gap
|
||||
// is greater than this value
|
||||
|
||||
/*
|
||||
* This Loader Module is written by Ilfak Guilfanov and
|
||||
* rewriten by Yury Haron
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Interesting documentation:
|
||||
|
||||
http://www.intel.com/design/zapcode/Intel_HEX_32_Format.doc
|
||||
http://www.keil.com/support/docs/1584.htm
|
||||
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
char str[80];
|
||||
if ( qlgets(str, sizeof(str), li) == NULL )
|
||||
return 0;
|
||||
|
||||
const char *p = str;
|
||||
while ( *p == ' ' )
|
||||
p++;
|
||||
|
||||
int type = 0;
|
||||
if ( qisxdigit((uchar)*(p+1)) && qisxdigit((uchar)*(p+2)) )
|
||||
{
|
||||
switch ( *p )
|
||||
{
|
||||
case ':':
|
||||
p = "Intel Hex Object Format";
|
||||
type = f_HEX;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
p = "MOS Technology Hex Object Format";
|
||||
type = f_MEX;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
p = "Motorola S-record Format";
|
||||
type = f_SREC;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if ( type != 0 )
|
||||
*fileformatname = p;
|
||||
return type;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// this struct was created to save space in the data segment (yes, we were
|
||||
// counting each byte at that time)
|
||||
static struct local_data
|
||||
{
|
||||
union
|
||||
{
|
||||
char *ptr; // load
|
||||
int sz; // write
|
||||
};
|
||||
union
|
||||
{
|
||||
uint32 ln; // load
|
||||
int size; // write
|
||||
};
|
||||
ushort sum; // load/write
|
||||
uchar len; // load
|
||||
} lc;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
NORETURN static void errfmt(void)
|
||||
{
|
||||
loader_failure("Bad hex input file format, line %u", lc.ln);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// reads the specified number of bytes from the input line
|
||||
// if size==0, then initializes itself for a new line
|
||||
static uint32 hexdata(int size)
|
||||
{
|
||||
int i = size;
|
||||
if ( i == 0 )
|
||||
{
|
||||
i = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( lc.len < i )
|
||||
errfmt();
|
||||
lc.len -= (uchar)i;
|
||||
i <<= 1;
|
||||
}
|
||||
char n[10];
|
||||
char *p = n;
|
||||
while ( i-- )
|
||||
*p++ = *lc.ptr++;
|
||||
*p = '\0';
|
||||
char *endp;
|
||||
uint32 data = strtoul(n, &endp, 16);
|
||||
if ( endp != p )
|
||||
errfmt();
|
||||
switch ( size )
|
||||
{
|
||||
case 0:
|
||||
lc.len = (uchar)data;
|
||||
lc.sum = lc.len;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
lc.sum += (uchar)(data >> 24);
|
||||
case 3:
|
||||
lc.sum += (uchar)(data >> 16);
|
||||
case 2:
|
||||
lc.sum += (uchar)(data >> 8);
|
||||
default: // 1
|
||||
lc.sum += (uchar)data;
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/)
|
||||
{
|
||||
memset(&lc, 0, sizeof(local_data));
|
||||
inf_set_start_ip(BADADDR); // f_SREC without start record
|
||||
|
||||
processor_t &ph = PH;
|
||||
bool iscode = (neflag & NEF_CODE) != 0;
|
||||
uint bs = iscode ? ph.cbsize() : ph.dbsize(); // number of bytes
|
||||
ea_t start_ea = to_ea(inf_get_baseaddr(), 0);
|
||||
sel_t sel = setup_selector(start_ea >> 4);
|
||||
bool segment_created = false;
|
||||
|
||||
bool cvt_to_bytes = false;
|
||||
if ( ph.id == PLFM_PIC )
|
||||
{
|
||||
// pic12xx and pic16xx use 12-bit and 14-bit words in program memory
|
||||
// pic18xx uses 16-bit opcodes but byte addressing
|
||||
if ( strncmp(inf_get_procname().c_str(), "PIC18", 5) != 0 )
|
||||
{
|
||||
static const char *const form =
|
||||
// "PIC HEX file addressing mode\n"
|
||||
// "\n"
|
||||
"There are two flavors of HEX files for PIC: with word addressing\n"
|
||||
"and with byte addressing. It is not possible to recognize the\n"
|
||||
"flavor automatically. Please specify what addressing mode should\n"
|
||||
"be used to load the input file. If you don't know, try both and\n"
|
||||
"choose the one which produces the more meaningful result\n";
|
||||
int code = ask_buttons("~B~yte addressing",
|
||||
"~W~ord addressing",
|
||||
"~C~ancel",
|
||||
1,
|
||||
form);
|
||||
switch ( code )
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 0:
|
||||
cvt_to_bytes = true;
|
||||
break;
|
||||
default:
|
||||
loader_failure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool bs_addr_scale = true;
|
||||
if ( ph.id == PLFM_TMS320C28 )
|
||||
bs_addr_scale = false;
|
||||
|
||||
filetype_t ftype = inf_get_filetype();
|
||||
char rstart = (ftype == f_SREC) ? 'S'
|
||||
: (ftype == f_HEX) ? ':'
|
||||
: ';';
|
||||
ea_t addr;
|
||||
ea_t end_ea = 0;
|
||||
ea_t seg_start = 0;
|
||||
ea_t subs_addr20 = 0;
|
||||
ea_t subs_addr32 = 0;
|
||||
bool bigaddr = false;
|
||||
char line[BUFFSIZE];
|
||||
for ( lc.ln = 1; qlgets(line, BUFFSIZE, li); lc.ln++ )
|
||||
{
|
||||
char *p = line;
|
||||
while ( *p == ' ' )
|
||||
++p;
|
||||
if ( *p == '\n' || *p == '\r' )
|
||||
continue;
|
||||
if ( *p++ != rstart )
|
||||
errfmt();
|
||||
|
||||
int sz = 2;
|
||||
int mode = (ftype == f_SREC) ? (uchar)*p++ : 0x100;
|
||||
lc.ptr = p;
|
||||
hexdata(0);
|
||||
if ( mode == 0x100 )
|
||||
{
|
||||
if ( !lc.len )
|
||||
break;
|
||||
lc.len += 2;
|
||||
if ( ftype == f_HEX )
|
||||
++lc.len;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( mode )
|
||||
{
|
||||
default:
|
||||
errfmt();
|
||||
|
||||
case '0':
|
||||
case '5':
|
||||
continue;
|
||||
|
||||
case '3':
|
||||
case '7':
|
||||
++sz;
|
||||
// fallthrough
|
||||
case '2':
|
||||
case '8':
|
||||
++sz;
|
||||
// fallthrough
|
||||
case '1':
|
||||
case '9':
|
||||
if ( mode > '3' )
|
||||
mode = 0;
|
||||
--lc.len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
addr = hexdata(sz);
|
||||
if ( ftype != f_SREC && bs_addr_scale )
|
||||
addr = addr / bs;
|
||||
if ( !mode )
|
||||
{
|
||||
inf_set_start_ip(addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ftype == f_HEX )
|
||||
{
|
||||
int type = hexdata(1); // record type
|
||||
switch ( type )
|
||||
{
|
||||
case 0xFF: // mitsubishi hex format
|
||||
case 4: // Extended linear address record (bits 16..31 of the start address)
|
||||
{
|
||||
uint32 seg_addr = uint32(hexdata(2) << 16);
|
||||
if ( bs_addr_scale )
|
||||
seg_addr /= bs;
|
||||
subs_addr32 = seg_addr;
|
||||
}
|
||||
break;
|
||||
case 2: // Extended segment address record (bits 4..19 of the start address)
|
||||
{
|
||||
uint32 seg_addr = uint32(hexdata(2) << 4);
|
||||
if ( bs_addr_scale )
|
||||
seg_addr /= bs;
|
||||
subs_addr20 = seg_addr;
|
||||
}
|
||||
break;
|
||||
case 5: // start address (ARM)
|
||||
{
|
||||
uint32 start_addr = hexdata(4);
|
||||
if ( ph.has_code16_bit() && (start_addr & 1) != 0 )
|
||||
{
|
||||
processor_t::set_code16_mode(start_addr, true);
|
||||
start_addr &= ~1;
|
||||
}
|
||||
inf_set_start_ip(start_addr);
|
||||
inf_set_start_ea(start_addr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( type != 0 )
|
||||
{
|
||||
if ( type == 1 )
|
||||
break; // end of file record
|
||||
continue; // not a data record
|
||||
}
|
||||
}
|
||||
// add the extended address bits
|
||||
addr += subs_addr20;
|
||||
addr += subs_addr32;
|
||||
if ( lc.len )
|
||||
{
|
||||
ea_t top = addr + lc.len / bs;
|
||||
p = line;
|
||||
while ( lc.len )
|
||||
{
|
||||
*p++ = (uchar)hexdata(1);
|
||||
if ( cvt_to_bytes ) // pic
|
||||
*p++ = '\0';
|
||||
}
|
||||
if ( top >= 0x10000 )
|
||||
bigaddr = true;
|
||||
addr += start_ea;
|
||||
show_addr(addr);
|
||||
top += start_ea;
|
||||
if ( top > end_ea || !segment_created )
|
||||
{
|
||||
asize_t delta = addr - end_ea;
|
||||
if ( delta >= SEGMENTGAP )
|
||||
segment_created = false; // force creation of new segment
|
||||
|
||||
end_ea = top;
|
||||
if ( neflag & NEF_SEGS )
|
||||
{
|
||||
if ( !segment_created )
|
||||
{
|
||||
if ( !add_segm(sel, addr, end_ea, NULL, iscode ? CLASS_CODE : CLASS_DATA) )
|
||||
loader_failure();
|
||||
segment_created = true;
|
||||
seg_start = addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
int flags = delta > SPARSE_GAP ? SEGMOD_SPARSE : 0;
|
||||
set_segm_end(seg_start, end_ea, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( seg_start > addr )
|
||||
{
|
||||
if ( (neflag & NEF_SEGS) != 0 )
|
||||
{
|
||||
int flags = seg_start-addr > SPARSE_GAP ? SEGMOD_SPARSE : 0;
|
||||
set_segm_start(seg_start, addr, flags);
|
||||
}
|
||||
seg_start = addr;
|
||||
}
|
||||
mem2base(line, addr, top, -1);
|
||||
}
|
||||
{
|
||||
ushort chi; // checksum
|
||||
++lc.len;
|
||||
switch ( ftype )
|
||||
{
|
||||
case f_SREC:
|
||||
chi = (uchar)(~lc.sum);
|
||||
chi ^= (uchar)hexdata(1);
|
||||
break;
|
||||
case f_HEX:
|
||||
hexdata(1);
|
||||
chi = (uchar)lc.sum;
|
||||
break;
|
||||
default: // MEX
|
||||
++lc.len;
|
||||
chi = lc.sum;
|
||||
chi -= (ushort)hexdata(2);
|
||||
break;
|
||||
}
|
||||
if ( chi )
|
||||
{
|
||||
static bool displayed = false;
|
||||
if ( !displayed )
|
||||
{
|
||||
displayed = true;
|
||||
warning("Bad hex input file checksum, line %u. Ignore?", lc.ln);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( (neflag & NEF_SEGS) != 0 )
|
||||
{
|
||||
if ( bigaddr )
|
||||
{
|
||||
set_segm_addressing(get_first_seg(), 1);
|
||||
if ( ph.id == PLFM_386 )
|
||||
inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT);
|
||||
}
|
||||
set_default_dataseg(sel);
|
||||
inf_set_start_cs(sel);
|
||||
}
|
||||
else
|
||||
{
|
||||
enable_flags(start_ea, end_ea, STT_CUR);
|
||||
}
|
||||
inf_set_af(inf_get_af() & ~AF_FINAL); // behave as a binary file
|
||||
|
||||
create_filename_cmt();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int set_s_type(ea_t addr)
|
||||
{
|
||||
int off = 0;
|
||||
lc.sz = 4;
|
||||
lc.size += 3;
|
||||
if ( addr >= 0x10000 )
|
||||
{
|
||||
++off;
|
||||
lc.sz += 2;
|
||||
lc.sum += (uchar)(addr >> 16);
|
||||
++lc.size;
|
||||
if ( addr >= 0x01000000 )
|
||||
{
|
||||
++off;
|
||||
lc.sz += 2;
|
||||
lc.sum += (uchar)(addr >> 24);
|
||||
++lc.size;
|
||||
}
|
||||
}
|
||||
return off;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
GCC_DIAG_OFF(format-nonliteral);
|
||||
int idaapi write_file(FILE *fp, const char * /*fileformatname*/)
|
||||
{
|
||||
//#define TEST_COMPILATION
|
||||
#ifdef TEST_COMPILATION
|
||||
# define DECL_FMT(x, y) static const char *const x = y
|
||||
#else
|
||||
# define DECL_FMT(x, y) static char x[] = y
|
||||
#endif
|
||||
DECL_FMT(fmt0, "%02X%0*" FMT_EA "X%s%0?X\r\n");
|
||||
DECL_FMT(fmt1, "?00?00001FF\r\n");
|
||||
DECL_FMT(fone, "%02X");
|
||||
|
||||
ea_t base = to_ea(inf_get_baseaddr(), 0);
|
||||
if ( inf_get_min_ea() < base )
|
||||
base = BADADDR;
|
||||
|
||||
if ( fp == NULL )
|
||||
{
|
||||
if ( inf_get_filetype() == f_SREC )
|
||||
return 1;
|
||||
ea_t ea1 = inf_get_max_ea() - inf_get_min_ea();
|
||||
if ( ea1 <= 0x10000 )
|
||||
return 1;
|
||||
ea_t strt = 0;
|
||||
ea_t addr;
|
||||
for ( addr = inf_get_min_ea(); addr < inf_get_max_ea(); )
|
||||
{
|
||||
segment_t *ps = getseg(addr);
|
||||
if ( ps == NULL || ps->type != SEG_IMEM )
|
||||
{
|
||||
if ( is_loaded(addr) )
|
||||
break;
|
||||
if ( base != BADADDR )
|
||||
{
|
||||
if ( --ea1 <= 0x10000 )
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++strt;
|
||||
}
|
||||
++addr;
|
||||
continue;
|
||||
}
|
||||
if ( strt )
|
||||
{
|
||||
ea1 -= strt;
|
||||
if ( ea1 != 0x10000 )
|
||||
return 1;
|
||||
strt = 0;
|
||||
}
|
||||
ea1 -= (ps->end_ea - addr);
|
||||
if ( ea1 < 0x10000 )
|
||||
return 1;
|
||||
++ea1;
|
||||
addr = ps->end_ea;
|
||||
}
|
||||
if ( base == BADADDR )
|
||||
{
|
||||
segment_t *ps = getseg(addr);
|
||||
ea1 -= (ps == NULL) ? addr : ps->start_ea;
|
||||
if ( ea1 <= 0x10000 )
|
||||
return 1;
|
||||
}
|
||||
if ( addr == inf_get_max_ea() )
|
||||
return 0;
|
||||
for ( base = inf_get_max_ea()-1; base > addr; )
|
||||
{
|
||||
segment_t *ps = getseg(base);
|
||||
if ( ps == NULL || ps->type != SEG_IMEM )
|
||||
{
|
||||
if ( is_loaded(base) )
|
||||
break;
|
||||
if ( --ea1 <= 0x10000 )
|
||||
return 1;
|
||||
--base;
|
||||
continue;
|
||||
}
|
||||
ea1 -= (base - ps->start_ea);
|
||||
if ( ea1 < 0x10000 )
|
||||
return 1;
|
||||
++ea1;
|
||||
base = ps->start_ea;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char ident;
|
||||
const char *found = qstrrchr(fmt0, '?');
|
||||
QASSERT(20067, found != NULL);
|
||||
int fmt0_marker = ((char *) found) - fmt0;
|
||||
fmt0[fmt0_marker] = '2';
|
||||
switch ( inf_get_filetype() )
|
||||
{
|
||||
case f_SREC:
|
||||
ident = 'S';
|
||||
break;
|
||||
case f_HEX:
|
||||
ident = ':';
|
||||
fmt1[3] = '0';
|
||||
break;
|
||||
default:
|
||||
ident = ';';
|
||||
fmt0[fmt0_marker] = '4';
|
||||
fmt1[3] = '\0';
|
||||
break;
|
||||
}
|
||||
fmt1[0] = ident;
|
||||
lc.sz = 4;
|
||||
|
||||
ea_t strt = inf_get_start_ip();
|
||||
for ( ea_t ea1 = inf_get_min_ea(); ea1 < inf_get_max_ea(); )
|
||||
{
|
||||
char str[(2 * MAX_BYTES) + 3];
|
||||
char *const end = str + sizeof(str);
|
||||
if ( !is_loaded(ea1) || segtype(ea1) == SEG_IMEM )
|
||||
{
|
||||
++ea1;
|
||||
continue;
|
||||
}
|
||||
if ( base == BADADDR )
|
||||
{
|
||||
segment_t *ps = getseg(ea1);
|
||||
base = ps == NULL ? ea1 : ps->start_ea;
|
||||
if ( strt != BADADDR )
|
||||
strt += inf_get_min_ea() - base;
|
||||
}
|
||||
ea_t addr = ea1 - base;
|
||||
lc.sum = (uchar)addr + (uchar)(addr >> 8);
|
||||
char *p = str;
|
||||
if ( inf_get_filetype() == f_HEX )
|
||||
{
|
||||
*p++ = '0';
|
||||
*p++ = '0';
|
||||
}
|
||||
lc.size = 0;
|
||||
do
|
||||
{
|
||||
uchar b = get_byte(ea1++);
|
||||
p += qsnprintf(p, end-p, fone, (unsigned)b);
|
||||
lc.sum += b;
|
||||
} while ( ++lc.size < MAX_BYTES
|
||||
&& ea1 < inf_get_max_ea()
|
||||
&& is_loaded(ea1)
|
||||
&& segtype(ea1) != SEG_IMEM );
|
||||
qfputc(ident, fp);
|
||||
if ( inf_get_filetype() == f_SREC )
|
||||
{
|
||||
char type = '1' + (char)set_s_type(addr);
|
||||
qfputc(type, fp);
|
||||
++lc.sum; // correct to NOT
|
||||
} // else addr = (ushort)addr; // force check
|
||||
lc.sum += (ushort)lc.size;
|
||||
if ( inf_get_filetype() != f_MEX )
|
||||
lc.sum = (uchar)(0-lc.sum);
|
||||
qfprintf(fp, fmt0, lc.size, lc.sz, addr, str, lc.sum);
|
||||
}
|
||||
if ( inf_get_filetype() != f_SREC )
|
||||
{
|
||||
qfprintf(fp, "%s", fmt1);
|
||||
}
|
||||
else if ( strt != BADADDR )
|
||||
{
|
||||
qfputc(ident, fp);
|
||||
lc.sum = 0;
|
||||
lc.size = 0;
|
||||
char type = '9' - (char)set_s_type(strt);
|
||||
qfputc(type, fp);
|
||||
lc.sum = (~(lc.size + lc.sum)) & 0xFF;
|
||||
qfprintf(fp, fmt0, lc.size, lc.sz, strt, &fone[sizeof(fone)-1], lc.sum);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
GCC_DIAG_ON(format-nonliteral);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
loader_t LDSC =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
LDRF_REQ_PROC, // requires the target processor to the set
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
write_file,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
13
idasdk76/ldr/hex/makefile
Normal file
13
idasdk76/ldr/hex/makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
PROC=hex
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)hex$(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 ../idaldr.h hex.cpp
|
||||
197
idasdk76/ldr/hpsom/common.cpp
Normal file
197
idasdk76/ldr/hpsom/common.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void sys_clock::swap(void)
|
||||
{
|
||||
secs = swap32(secs);
|
||||
nanosecs = swap32(nanosecs);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void header::swap(void)
|
||||
{
|
||||
system_id= swap16(system_id);
|
||||
a_magic= swap16(a_magic);
|
||||
file_time.swap();
|
||||
version_id= swap32(version_id);
|
||||
entry_space= swap32(entry_space);
|
||||
entry_subspace= swap32(entry_subspace);
|
||||
entry_offset= swap32(entry_offset);
|
||||
aux_header_location= swap32(aux_header_location);
|
||||
aux_header_size= swap32(aux_header_size);
|
||||
som_length= swap32(som_length);
|
||||
presumed_dp= swap32(presumed_dp);
|
||||
space_location= swap32(space_location);
|
||||
space_total= swap32(space_total);
|
||||
subspace_location= swap32(subspace_location);
|
||||
subspace_total= swap32(subspace_total);
|
||||
loader_fixup_location= swap32(loader_fixup_location);
|
||||
loader_fixup_total= swap32(loader_fixup_total);
|
||||
space_strings_location= swap32(space_strings_location);
|
||||
space_strings_size= swap32(space_strings_size);
|
||||
init_array_location= swap32(init_array_location);
|
||||
init_array_total= swap32(init_array_total);
|
||||
compiler_location= swap32(compiler_location);
|
||||
compiler_total= swap32(compiler_total);
|
||||
symbol_location= swap32(symbol_location);
|
||||
symbol_total= swap32(symbol_total);
|
||||
fixup_request_location= swap32(fixup_request_location);
|
||||
fixup_request_total= swap32(fixup_request_total);
|
||||
symbol_strings_location= swap32(symbol_strings_location);
|
||||
symbol_strings_size= swap32(symbol_strings_size);
|
||||
unloadable_sp_location= swap32(unloadable_sp_location);
|
||||
unloadable_sp_size= swap32(unloadable_sp_size);
|
||||
checksum= swap32(checksum);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void aux_id::swap(void)
|
||||
{
|
||||
type = swap16(type);
|
||||
length = swap32(length);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void som_exec_auxhdr::swap(void)
|
||||
{
|
||||
header_id.swap();
|
||||
exec_tsize = swap32(exec_tsize); /* text size */
|
||||
exec_tmem = swap32(exec_tmem); /* start address of text */
|
||||
exec_tfile = swap32(exec_tfile); /* file ptr to text */
|
||||
exec_dsize = swap32(exec_dsize); /* data size */
|
||||
exec_dmem = swap32(exec_dmem); /* start address of data */
|
||||
exec_dfile = swap32(exec_dfile); /* file ptr to data */
|
||||
exec_bsize = swap32(exec_bsize); /* bss size */
|
||||
exec_entry = swap32(exec_entry); /* address of entry point */
|
||||
exec_flags = swap32(exec_flags); /* loader flags */
|
||||
exec_bfill = swap32(exec_bfill); /* bss initialization value */
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void user_string_aux_hdr::swap(void) /* Version string auxiliary header */
|
||||
{
|
||||
header_id.swap();
|
||||
string_length = swap32(string_length); /* strlen(user_string) */
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void copyright_aux_hdr::swap(void)
|
||||
{
|
||||
header_id.swap();
|
||||
string_length = swap32(string_length); /* strlen(user_string) */
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void shlib_version_aux_hdr::swap(void)
|
||||
{
|
||||
header_id.swap();
|
||||
version = swap16(version); /* version number */
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void space_dictionary_record::swap(void)
|
||||
{
|
||||
name.n_strx = swap32(name.n_strx);
|
||||
space_number = swap32(space_number);
|
||||
subspace_index = swap32(subspace_index);
|
||||
subspace_quantity = swap32(subspace_quantity);
|
||||
loader_fix_index = swap32(loader_fix_index);
|
||||
loader_fix_quantity = swap32(loader_fix_quantity);
|
||||
init_pointer_index = swap32(init_pointer_index);
|
||||
init_pointer_quantity = swap32(init_pointer_quantity);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void subspace_dictionary_record::swap(void)
|
||||
{
|
||||
space_index = swap32(space_index);
|
||||
file_loc_init_value = swap32(file_loc_init_value);
|
||||
initialization_length = swap32(initialization_length);
|
||||
subspace_start = swap32(subspace_start);
|
||||
subspace_length = swap32(subspace_length);
|
||||
reserved2 = swap16(reserved2);
|
||||
alignment = swap16(alignment);
|
||||
name.n_strx = swap32(name.n_strx);
|
||||
fixup_request_index = swap32(fixup_request_index);
|
||||
fixup_request_quantity = swap32(fixup_request_quantity);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void symbol_dictionary_record::swap(void)
|
||||
{
|
||||
name.n_strx = swap32(name.n_strx);
|
||||
qualifier_name.n_strx = swap32(qualifier_name.n_strx);
|
||||
symbol_info = swap32(symbol_info);
|
||||
symbol_value = swap32(symbol_value);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void dl_header::swap(void)
|
||||
{
|
||||
hdr_version = swap32(hdr_version);
|
||||
ltptr_value = swap32(ltptr_value);
|
||||
shlib_list_loc = swap32(shlib_list_loc);
|
||||
shlib_list_count = swap32(shlib_list_count);
|
||||
import_list_loc = swap32(import_list_loc);
|
||||
import_list_count = swap32(import_list_count);
|
||||
hash_table_loc = swap32(hash_table_loc);
|
||||
hash_table_size = swap32(hash_table_size);
|
||||
export_list_loc = swap32(export_list_loc);
|
||||
export_list_count = swap32(export_list_count);
|
||||
string_table_loc = swap32(string_table_loc);
|
||||
string_table_size = swap32(string_table_size);
|
||||
dreloc_loc = swap32(dreloc_loc);
|
||||
dreloc_count = swap32(dreloc_count);
|
||||
dlt_loc = swap32(dlt_loc);
|
||||
plt_loc = swap32(plt_loc);
|
||||
dlt_count = swap32(dlt_count);
|
||||
plt_count = swap32(plt_count);
|
||||
highwater_mark = swap16(highwater_mark);
|
||||
flags = swap16(flags);
|
||||
export_ext_loc = swap32(export_ext_loc);
|
||||
module_loc = swap32(module_loc);
|
||||
module_count = swap32(module_count);
|
||||
elaborator = swap32(elaborator);
|
||||
initializer = swap32(initializer);
|
||||
embedded_path = swap32(embedded_path);
|
||||
initializer_count = swap32(initializer_count);
|
||||
tdsize = swap32(tdsize);
|
||||
fastbind_list_loc = swap32(fastbind_list_loc);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void import_entry::swap(void)
|
||||
{
|
||||
name = swap32(name);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void misc_info::swap(void)
|
||||
{
|
||||
version = swap16(version);
|
||||
flags = swap16(flags);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void export_entry::swap(void)
|
||||
{
|
||||
next = swap32(next);
|
||||
name = swap32(name);
|
||||
value = swap32(value);
|
||||
if ( type == ST_STORAGE )
|
||||
info.size = swap32(info.size);
|
||||
else
|
||||
info.misc.swap();
|
||||
module_index = swap16(module_index);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static uint32 compute_som_checksum(void *p)
|
||||
{
|
||||
int n = sizeof(header) / sizeof(uint32);
|
||||
uint32 *ptr = (uint32 *)p;
|
||||
uint32 sum = 0;
|
||||
for ( int i=0; i < n; i++ )
|
||||
sum ^= *ptr++;
|
||||
return sum;
|
||||
}
|
||||
|
||||
441
idasdk76/ldr/hpsom/hpsom.cpp
Normal file
441
idasdk76/ldr/hpsom/hpsom.cpp
Normal file
@@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2000 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include <typeinf.hpp>
|
||||
#include "hpsom.hpp"
|
||||
|
||||
#include "common.cpp"
|
||||
|
||||
static int first_text_subspace_idx = -1;
|
||||
static int32 first_text_subspace_fpos = -1;
|
||||
static char *dl_strings = NULL;
|
||||
static size_t dl_ssize = 0;
|
||||
static ea_t data_start = 0;
|
||||
static int64 fsize = 0;
|
||||
//--------------------------------------------------------------------------
|
||||
static void complain_fixup(void)
|
||||
{
|
||||
static bool complained = false;
|
||||
if ( !complained )
|
||||
{
|
||||
warning("The input file contains relocation information.\n"
|
||||
"Currently IDA doesn't handle relocation information,\n"
|
||||
"so it will be skipped");
|
||||
complained = true;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
header h;
|
||||
qlseek(li, 0);
|
||||
if ( qlread(li, &h, sizeof(h)) != sizeof(h) )
|
||||
return 0;
|
||||
if ( compute_som_checksum(&h) != 0 )
|
||||
return 0;
|
||||
h.swap();
|
||||
const char *type;
|
||||
switch ( h.a_magic )
|
||||
{
|
||||
case EXELIB_MAGIC : type = "Executable Library"; break;
|
||||
case REL_MAGIC : type = "Relocatable"; break;
|
||||
case EXE_MAGIC : type = "Non-sharable, executable"; break;
|
||||
case SHREXE_MAGIC : type = "Sharable, executable"; break;
|
||||
case SHREXELD_MAGIC: type = "Sharable, demand-loadable executable"; break;
|
||||
case DLL_MAGIC : type = "Dynamic Load Library"; break;
|
||||
case SHLIB_MAGIC : type = "Shared Library"; break;
|
||||
case RELLIB_MAGIC : type = "Relocatable Library"; break;
|
||||
default: return 0;
|
||||
}
|
||||
fileformatname->sprnt("HP-UX SOM (%s)", type);
|
||||
*processor = "hppa";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_aux_headers(linput_t *li, int32 fpos, size_t size)
|
||||
{
|
||||
if ( size == 0 )
|
||||
return;
|
||||
|
||||
size_t rest = fsize - fpos;
|
||||
if ( rest <= size )
|
||||
loader_failure("Wrong header::aux_header_size");
|
||||
qlseek(li, fpos);
|
||||
|
||||
while ( size > 0 )
|
||||
{
|
||||
char buf[4096];
|
||||
CASSERT(sizeof(buf) >= sizeof(aux_id));
|
||||
aux_id &aih = *(aux_id *)buf;
|
||||
lread(li, &aih, sizeof(aih));
|
||||
aih.swap();
|
||||
size_t total = sizeof(aih) + aih.length;
|
||||
if ( total < sizeof(aih) || total >= sizeof(buf) )
|
||||
loader_failure("Wrong aux_header size %" FMT_Z, total);
|
||||
if ( total > size )
|
||||
return; // loader_failure("Illegal aux header size %u, rest %u", total, size);
|
||||
size -= total;
|
||||
lread(li, &aih+1, aih.length);
|
||||
switch ( aih.type )
|
||||
{
|
||||
case HPUX_AUX_ID:
|
||||
{
|
||||
som_exec_auxhdr *p = (som_exec_auxhdr*)buf;
|
||||
p->swap();
|
||||
inf_set_start_cs(0);
|
||||
inf_set_start_ip(p->exec_entry);
|
||||
data_start = p->exec_dmem;
|
||||
}
|
||||
break;
|
||||
case VERSION_AUX_ID:
|
||||
case COPYRIGHT_AUX_ID:
|
||||
case SHLIB_VERSION_AUX_ID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static char *get_name(linput_t *li, int32 tableoff, size_t tablesize, int32 nidx, char *buf, size_t bufsize)
|
||||
{
|
||||
if ( nidx >= tablesize )
|
||||
{
|
||||
APPZERO(buf, buf+bufsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
qoff64_t fpos = qltell(li);
|
||||
qlseek(li, tableoff+nidx-4);
|
||||
uint32 len;
|
||||
lread(li, &len, sizeof(len));
|
||||
len = swap32(len);
|
||||
if ( len >= bufsize )
|
||||
len = uint32(bufsize-1);
|
||||
lread(li, buf, len);
|
||||
buf[len] = '\0';
|
||||
qlseek(li, fpos);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline char *get_space_name(linput_t *li, const header &h, int32 nidx, char *buf, size_t bufsize)
|
||||
{
|
||||
return get_name(li,
|
||||
h.space_strings_location,
|
||||
h.space_strings_size,
|
||||
nidx,
|
||||
buf,
|
||||
bufsize);
|
||||
}
|
||||
|
||||
inline char *get_symbol_name(linput_t *li, const header &h, int32 nidx, char *buf, size_t bufsize)
|
||||
{
|
||||
return get_name(li,
|
||||
h.symbol_strings_location,
|
||||
h.symbol_strings_size,
|
||||
nidx,
|
||||
buf,
|
||||
bufsize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_spaces(linput_t *li, const header &h, int32 fpos, int n)
|
||||
{
|
||||
if ( n == 0 )
|
||||
return;
|
||||
|
||||
qlseek(li, fpos);
|
||||
space_dictionary_record sr;
|
||||
validate_array_count_or_die(li, n, sizeof(sr), "Number of spaces", fpos);
|
||||
for ( int i=0; i < n; i++ )
|
||||
{
|
||||
lread(li, &sr, sizeof(sr));
|
||||
sr.swap();
|
||||
char buf[MAXSTR];
|
||||
get_space_name(li, h, sr.name.n_strx, buf, sizeof(buf));
|
||||
if ( streq(buf, "$TEXT$") )
|
||||
first_text_subspace_idx = sr.subspace_index;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_subspaces(linput_t *li, const header &h, qoff64_t fpos, int n)
|
||||
{
|
||||
if ( n == 0 )
|
||||
return;
|
||||
subspace_dictionary_record sr;
|
||||
validate_array_count_or_die(li, n, sizeof(sr), "Number of subspaces", fpos);
|
||||
for ( int i=0; i < n; i++,fpos+=sizeof(sr) )
|
||||
{
|
||||
qlseek(li, fpos);
|
||||
lread(li, &sr, sizeof(sr));
|
||||
sr.swap();
|
||||
|
||||
if ( !sr.is_loadable() || !sr.subspace_length )
|
||||
continue;
|
||||
if ( sr.fixup_request_quantity )
|
||||
complain_fixup();
|
||||
ea_t start = sr.subspace_start;
|
||||
ea_t end = start + sr.initialization_length;
|
||||
qoff64_t fpos2 = sr.file_loc_init_value;
|
||||
if ( end < start || fpos2 > fsize || fsize-fpos2 < end-start )
|
||||
loader_failure("Wrong segment size %a..%a", start, end);
|
||||
file2base(li, fpos2, start, end, FILEREG_PATCHABLE);
|
||||
char buf[MAXSTR];
|
||||
char *name = get_space_name(li, h, sr.name.n_strx, buf, sizeof(buf));
|
||||
set_selector(i, 0);
|
||||
const char *sclass = strstr(name, "CODE") != NULL ? CLASS_CODE : CLASS_DATA;
|
||||
|
||||
segment_t s;
|
||||
s.sel = setup_selector(i);
|
||||
s.start_ea = start;
|
||||
s.end_ea = start + sr.subspace_length;
|
||||
s.align = saRelByte;
|
||||
s.comb = scPub;
|
||||
s.bitness = (uchar)PH.get_segm_bitness();
|
||||
if ( !add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed to create segment %a..%a", s.start_ea, s.end_ea);
|
||||
|
||||
if ( i == first_text_subspace_idx )
|
||||
first_text_subspace_fpos = sr.file_loc_init_value;
|
||||
// sr.alignment,
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_symbols(linput_t *li, const header &h, int32 fpos, int n)
|
||||
{
|
||||
if ( n == 0 )
|
||||
return;
|
||||
qlseek(li, fpos);
|
||||
symbol_dictionary_record sr;
|
||||
validate_array_count_or_die(li, n, sizeof(sr), "Number of symbols", fpos);
|
||||
for ( int i=0; i < n; i++ )
|
||||
{
|
||||
lread(li, &sr, sizeof(sr));
|
||||
sr.swap();
|
||||
if ( sr.symbol_scope() == SS_UNSAT )
|
||||
continue;
|
||||
char buf[MAXSTR];
|
||||
char *name = get_symbol_name(li, h, sr.name.n_strx, buf, sizeof(buf));
|
||||
ea_t ea = sr.symbol_value & ~3;
|
||||
switch ( sr.symbol_type() )
|
||||
{
|
||||
case ST_NULL:
|
||||
case ST_ABSOLUTE:
|
||||
break;
|
||||
case ST_DATA:
|
||||
force_name(ea, name, SN_IDBENC);
|
||||
break;
|
||||
case ST_STUB:
|
||||
append_cmt(ea, "STUB", false);
|
||||
// fallthrough
|
||||
case ST_CODE:
|
||||
case ST_ENTRY:
|
||||
case ST_MILLICODE:
|
||||
case ST_MILLI_EXT:
|
||||
add_entry(ea, ea, name, true, AEF_IDBENC);
|
||||
add_entry(ea, ea, name, true, AEF_IDBENC);
|
||||
break;
|
||||
case ST_PRI_PROG:
|
||||
case ST_STORAGE:
|
||||
case ST_MODULE:
|
||||
case ST_SYM_EXT:
|
||||
case ST_ARG_EXT:
|
||||
case ST_PLABEL:
|
||||
case ST_OCT_DIS:
|
||||
case ST_TSTORAGE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static char *get_text_name(int nidx, char *buf, size_t bufsize)
|
||||
{
|
||||
if ( nidx == -1 )
|
||||
return NULL;
|
||||
if ( nidx >= 0 && nidx < dl_ssize )
|
||||
qstrncpy(buf, dl_strings + nidx, bufsize);
|
||||
else
|
||||
qsnprintf(buf, bufsize, "0x%08X", nidx);
|
||||
return buf;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_imports(linput_t *li, const dl_header &dl)
|
||||
{
|
||||
if ( dl.import_list_count == 0 )
|
||||
return;
|
||||
qoff64_t fpos = first_text_subspace_fpos + dl.import_list_loc;
|
||||
qlseek(li, fpos);
|
||||
ea_t ea = data_start + dl.dlt_loc;
|
||||
int n = dl.dlt_count;
|
||||
import_entry ie;
|
||||
validate_array_count_or_die(li, dl.import_list_count, sizeof(ie), "Number of imports", fpos);
|
||||
for ( int i=0; i < dl.import_list_count; i++ )
|
||||
{
|
||||
lread(li, &ie, sizeof(ie));
|
||||
ie.swap();
|
||||
if ( n == 0 )
|
||||
ea = data_start + dl.plt_loc;
|
||||
n--;
|
||||
char buf[MAXSTR];
|
||||
buf[0] = '.';
|
||||
get_text_name(ie.name, &buf[1], sizeof(buf)-1);
|
||||
force_name(ea, buf, SN_IDBENC);
|
||||
create_dword(ea, 4);
|
||||
op_plain_offset(ea, 0, 0);
|
||||
if ( n > 0 )
|
||||
{
|
||||
ea += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
ea_t ea2 = get_dword(ea);
|
||||
force_name(ea2, &buf[1], SN_IDBENC);
|
||||
add_func(ea2);
|
||||
set_func_cmt(get_func(ea2), "THUNK", false);
|
||||
create_dword(ea+4, 4);
|
||||
ea += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_exports(linput_t *li, const dl_header &dl)
|
||||
{
|
||||
if ( dl.export_list_count == 0 )
|
||||
return;
|
||||
export_entry ee;
|
||||
qoff64_t fpos = first_text_subspace_fpos + dl.export_list_loc;
|
||||
qlseek(li, fpos);
|
||||
validate_array_count_or_die(li, dl.export_list_count, sizeof(ee), "Number of exports", fpos);
|
||||
for ( int i=0; i < dl.export_list_count; i++ )
|
||||
{
|
||||
lread(li, &ee, sizeof(ee));
|
||||
ee.swap();
|
||||
char buf[MAXSTR];
|
||||
const char *name = get_text_name(ee.name, buf, sizeof(buf));
|
||||
add_entry(ee.value, ee.value, name, ee.type == ST_CODE, AEF_IDBENC);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void load_dl_header(linput_t *li)
|
||||
{
|
||||
if ( first_text_subspace_fpos == -1 )
|
||||
return;
|
||||
qlseek(li, first_text_subspace_fpos);
|
||||
dl_header dl;
|
||||
lread(li, &dl, sizeof(dl));
|
||||
dl.swap();
|
||||
switch ( dl.hdr_version )
|
||||
{
|
||||
case OLD_HDR_VERSION: break;
|
||||
case HDR_VERSION: break;
|
||||
default:
|
||||
msg("Unknown DL header version, skipping...\n");
|
||||
}
|
||||
if ( dl.string_table_size != 0 )
|
||||
{
|
||||
qoff64_t fpos = first_text_subspace_fpos + dl.string_table_loc;
|
||||
qlseek(li, fpos);
|
||||
dl_ssize = dl.string_table_size;
|
||||
validate_array_count_or_die(li, dl_ssize, 1, "String table size", fpos);
|
||||
dl_strings = (char *)qalloc(dl_ssize);
|
||||
if ( dl_strings == NULL )
|
||||
nomem("dl_strings");
|
||||
lread(li, dl_strings, dl_ssize);
|
||||
}
|
||||
if ( dl.dreloc_count != 0 )
|
||||
complain_fixup();
|
||||
|
||||
load_imports(li, dl);
|
||||
load_exports(li, dl);
|
||||
|
||||
qfree(dl_strings);
|
||||
dl_strings = NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
set_processor_type("hppa", SETPROC_LOADER);
|
||||
|
||||
header h;
|
||||
qlseek(li, 0);
|
||||
lread(li, &h, sizeof(h));
|
||||
h.swap();
|
||||
inf_set_baseaddr(0);
|
||||
|
||||
fsize = qlsize(li);
|
||||
load_aux_headers(li, h.aux_header_location, h.aux_header_size);
|
||||
load_spaces(li, h, h.space_location, h.space_total);
|
||||
load_subspaces(li, h, h.subspace_location, h.subspace_total);
|
||||
load_symbols(li, h, h.symbol_location, h.symbol_total);
|
||||
load_dl_header(li);
|
||||
create_filename_cmt();
|
||||
|
||||
size_t dp = h.presumed_dp;
|
||||
if ( dp == 0 )
|
||||
{
|
||||
// 23 61 28 00 ldil ...., %dp
|
||||
// 37 7B 01 60 ldo 0xB0(%dp), %dp
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, inf_get_start_ip()) > 0
|
||||
&& insn.Op1.type == o_imm
|
||||
&& insn.Op2.type == o_reg )
|
||||
{
|
||||
uval_t v = insn.Op1.value;
|
||||
if ( decode_insn(&insn, insn.ea+4) && insn.Op1.type == o_displ )
|
||||
dp = size_t(v + insn.Op1.addr);
|
||||
}
|
||||
}
|
||||
|
||||
if ( dp != 0 )
|
||||
set_gotea(dp);
|
||||
|
||||
add_til("hpux", ADDTIL_DEFAULT);
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
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,
|
||||
};
|
||||
542
idasdk76/ldr/hpsom/hpsom.hpp
Normal file
542
idasdk76/ldr/hpsom/hpsom.hpp
Normal file
@@ -0,0 +1,542 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2000 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HPSOM_HPP
|
||||
#define HPSOM_HPP
|
||||
|
||||
// The timestamp is a two-word structure as shown below. If unused, both fields are
|
||||
// zero.
|
||||
|
||||
struct sys_clock
|
||||
{
|
||||
uint secs;
|
||||
uint nanosecs;
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
struct header
|
||||
{
|
||||
short system_id; /* system id */
|
||||
#define SYSTEM_10 0x20B // PA-RISC 1.0
|
||||
#define SYSTEM_11 0x210 // PA-RISC 1.1
|
||||
#define SYSTEM_20 0x214 // PA-RISC 2.0
|
||||
short int a_magic; /* magic number */
|
||||
#define EXELIB_MAGIC 0x104 // Executable SOM Library
|
||||
#define REL_MAGIC 0x106 // Relocatable SOM
|
||||
#define EXE_MAGIC 0x107 // Non-sharable, executable SOM
|
||||
#define SHREXE_MAGIC 0x108 // Sharable, executable SOM
|
||||
#define SHREXELD_MAGIC 0x10B // Sharable, demand-loadable executable SOM
|
||||
#define DLL_MAGIC 0x10D // Dynamic Load Library
|
||||
#define SHLIB_MAGIC 0x10E // Shared Library
|
||||
#define RELLIB_MAGIC 0x619 // Relocatable SOM Library
|
||||
uint version_id; /* a.out format version */
|
||||
struct sys_clock file_time; /* timestamp */
|
||||
uint entry_space; /* index of space containing entry point */
|
||||
uint entry_subspace; /* subspace index of entry */
|
||||
uint entry_offset; /* offset of entry point */
|
||||
uint aux_header_location; /* file ptr to aux hdrs */
|
||||
uint aux_header_size; /* sizeof aux hdrs */
|
||||
uint som_length; /* length of object module */
|
||||
uint presumed_dp; /* DP value assumed during compilation */
|
||||
uint space_location; /* file ptr to space dict */
|
||||
uint space_total; /* # of spaces */
|
||||
uint subspace_location; /* file ptr to subsp dict */
|
||||
uint subspace_total; /* # of subspaces */
|
||||
uint loader_fixup_location; /* space reference array */
|
||||
uint loader_fixup_total; /* # of space reference recs */
|
||||
uint space_strings_location; /* file ptr to sp. strings */
|
||||
uint space_strings_size; /* sizeof sp. strings */
|
||||
uint init_array_location; /* location of init pointers */
|
||||
uint init_array_total; /* # of init pointers */
|
||||
uint compiler_location; /* file ptr to comp recs */
|
||||
uint compiler_total; /* # of compiler recs */
|
||||
uint symbol_location; /* file ptr to sym table */
|
||||
uint symbol_total; /* # of symbols */
|
||||
uint fixup_request_location; /* file ptr to fixups */
|
||||
uint fixup_request_total; /* # of fixups */
|
||||
uint symbol_strings_location; /* file ptr to sym strings */
|
||||
uint symbol_strings_size; /* sizeof sym strings */
|
||||
uint unloadable_sp_location; /* file ptr to debug info */
|
||||
uint unloadable_sp_size; /* size of debug info */
|
||||
uint checksum; /* header checksum */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Auxiliary Headers
|
||||
//
|
||||
// The auxiliary headers are contained in a single contiguous area in the file, and
|
||||
// are located by a pointer in the file header. Auxiliary headers are used for two
|
||||
// purposes: to attach users' version and copyright strings to an object file, and
|
||||
// to contain the information needed to load an executable program. In an
|
||||
// executable program, the HP-UX auxiliary header must precede all other auxiliary
|
||||
// headers.
|
||||
|
||||
struct aux_id
|
||||
{
|
||||
unsigned char flags;
|
||||
#define AUX_MANDATORY 0x10 /* linker must understand aux hdr info */
|
||||
#define AUX_COPY 0x20 /* copy aux hdr without modification */
|
||||
#define AUX_APPEND 0x40 /* merge multiple entries of same type */
|
||||
#define AUX_IGNORE 0x80 /* ignore aux hdr if type unknown */
|
||||
|
||||
bool mandatory(void) { return (flags & AUX_MANDATORY) != 0; }
|
||||
bool copy(void) { return (flags & AUX_COPY ) != 0; }
|
||||
bool append(void) { return (flags & AUX_APPEND ) != 0; }
|
||||
bool ignore(void) { return (flags & AUX_IGNORE ) != 0; }
|
||||
|
||||
uchar reserved;
|
||||
ushort type; /* aux hdr type */
|
||||
uint length; /* sizeof rest of aux hdr */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
/* Values for the aux_id.type field */
|
||||
#define HPUX_AUX_ID 4
|
||||
#define VERSION_AUX_ID 6
|
||||
#define COPYRIGHT_AUX_ID 9
|
||||
#define SHLIB_VERSION_AUX_ID 10
|
||||
|
||||
struct som_exec_auxhdr /* HP-UX auxiliary header */
|
||||
{
|
||||
struct aux_id header_id; /* aux header id */
|
||||
int32 exec_tsize; /* text size */
|
||||
int32 exec_tmem; /* start address of text */
|
||||
int32 exec_tfile; /* file ptr to text */
|
||||
int32 exec_dsize; /* data size */
|
||||
int32 exec_dmem; /* start address of data */
|
||||
int32 exec_dfile; /* file ptr to data */
|
||||
int32 exec_bsize; /* bss size */
|
||||
int32 exec_entry; /* address of entry point */
|
||||
int32 exec_flags; /* loader flags */
|
||||
int32 exec_bfill; /* bss initialization value */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
/* Values for exec_flags */
|
||||
#define TRAP_NIL_PTRS 01
|
||||
|
||||
struct user_string_aux_hdr /* Version string auxiliary header */
|
||||
{
|
||||
struct aux_id header_id; /* aux header id */
|
||||
uint string_length; /* strlen(user_string) */
|
||||
char user_string[1]; /* user-defined string */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
struct copyright_aux_hdr /* Copyright string auxiliary header */
|
||||
{
|
||||
struct aux_id header_id; /* aux header id */
|
||||
uint string_length; /* strlen(user_string) */
|
||||
char copyright[1]; /* user-defined string */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
struct shlib_version_aux_hdr
|
||||
{
|
||||
struct aux_id header_id; /* aux header id */
|
||||
short version; /* version number */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Space Dictionary
|
||||
//
|
||||
// The space dictionary consists of a sequence of space records
|
||||
//
|
||||
// The strings for the space names are contained in the space strings table, which
|
||||
// is located by a pointer in the file header. Each entry in the space strings
|
||||
// table is preceded by a 4-byte integer that defines the length of the string, and
|
||||
// is terminated by one to five null characters to pad the string out to a word
|
||||
// boundary. Indices to this table are relative to the start of the table, and
|
||||
// point to the first byte of the string (not the preceding length word). The union
|
||||
// defined above is used for all such string pointers; the character pointer is
|
||||
// defined for programs that read the string table into memory and wish to relocate
|
||||
// in-memory copies of space records.
|
||||
|
||||
|
||||
|
||||
union name_pt
|
||||
{
|
||||
// char *n_name;
|
||||
uint n_strx;
|
||||
};
|
||||
|
||||
struct space_dictionary_record
|
||||
{
|
||||
union name_pt name; /* index to space name */
|
||||
|
||||
unsigned char flags;
|
||||
#define SPACE_IS_LOADABLE 0x80 /* space is loadable */
|
||||
#define SPACE_IS_DEFINED 0x40 /* space is defined within file */
|
||||
#define SPACE_IS_PRIVATE 0x20 /* space is not sharable */
|
||||
#define SPACE_HAS_INTERM 0x10 /* contains intermediate code */
|
||||
#define SPACE_IS_TSPEC 0x08 /* space is $thread_specific$ */
|
||||
bool is_loadable(void) { return (flags & SPACE_IS_LOADABLE) != 0; }
|
||||
bool is_defined(void) { return (flags & SPACE_IS_DEFINED ) != 0; }
|
||||
bool is_private(void) { return (flags & SPACE_IS_PRIVATE ) != 0; }
|
||||
bool has_intermediate_code(void) { return (flags & SPACE_HAS_INTERM ) != 0; }
|
||||
bool is_tspecific(void) { return (flags & SPACE_IS_TSPEC ) != 0; }
|
||||
unsigned char reserved;
|
||||
unsigned char sort_key; /* sort key for space */
|
||||
unsigned char reserved2; /* reserved */
|
||||
|
||||
int space_number; /* space index */
|
||||
int subspace_index; /* index to first subspace */
|
||||
uint subspace_quantity; /* # of subspaces in space */
|
||||
int loader_fix_index; /* index into loader fixup array */
|
||||
uint loader_fix_quantity; /* # of loader fixups in space */
|
||||
int init_pointer_index; /* index into init pointer array */
|
||||
uint init_pointer_quantity; /* # of init ptrs */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Subspace Dictionary
|
||||
//
|
||||
// The subspace dictionary consists of a sequence of subspace records, as defined
|
||||
// in <scnhdr.h>. Strings for subspace names are contained in the space strings
|
||||
// table.
|
||||
|
||||
struct subspace_dictionary_record
|
||||
{
|
||||
int space_index; /* index into space dictionary */
|
||||
|
||||
unsigned char f1;
|
||||
#define SUBS_F1_ACCESS 0xFE /* access and priv levels of subsp */
|
||||
#define SUBS_F1_MEMRES 0x01 /* lock in memory during exec */
|
||||
int access_control_bits(void) { return (f1 & SUBS_F1_ACCESS) >> 1; }
|
||||
bool memory_resident(void) { return (f1 & SUBS_F1_MEMRES) != 0; }
|
||||
|
||||
unsigned char f2;
|
||||
#define SUBS_F2_DUPCOM 0x80 /* duplicate data symbols allowed */
|
||||
#define SUBS_F2_INICOM 0x40 /* initialized common block */
|
||||
#define SUBS_F2_ISLOAD 0x20 /* subspace is loadable */
|
||||
#define SUBS_F2_QUADR 0x18 /* quadrant in space subsp should reside in */
|
||||
#define SUBS_F2_FROZEN 0x04 /* lock in memory when OS booted */
|
||||
#define SUBS_F2_FIRST 0x02 /* must be first subspace */
|
||||
#define SUBS_F2_CODE 0x01 /* subspace contains only code */
|
||||
bool dup_common(void) { return (f2 & SUBS_F2_DUPCOM) != 0; }
|
||||
bool is_common(void) { return (f2 & SUBS_F2_INICOM) != 0; }
|
||||
bool is_loadable(void) { return (f2 & SUBS_F2_ISLOAD) != 0; }
|
||||
int quadrant(void) { return (f2 & SUBS_F2_QUADR ) >> 3; }
|
||||
bool initially_frozen(void) { return (f2 & SUBS_F2_FROZEN) != 0; }
|
||||
bool is_first(void) { return (f2 & SUBS_F2_FIRST ) != 0; }
|
||||
bool code_only(void) { return (f2 & SUBS_F2_CODE ) != 0; }
|
||||
|
||||
unsigned char sort_key; /* subspace sort key */
|
||||
|
||||
unsigned char f3;
|
||||
#define SUBS_F3_REPINI 0x80 /* init values to be replicated to fill subsp len */
|
||||
#define SUBS_F3_CONTIN 0x40 /* subspace is a continuation */
|
||||
#define SUBS_F3_ISTSPC 0x20 /* subspace contains TLS */
|
||||
bool replicate_init(void) { return (f3 & SUBS_F3_REPINI) != 0; }
|
||||
bool continuation(void) { return (f3 & SUBS_F3_CONTIN) != 0; }
|
||||
bool is_tspecific(void) { return (f3 & SUBS_F3_ISTSPC) != 0; }
|
||||
|
||||
int file_loc_init_value; /* file location or init value */
|
||||
uint initialization_length; /* length of initialization */
|
||||
uint subspace_start; /* starting offset */
|
||||
uint subspace_length; /* total subspace length */
|
||||
unsigned short reserved2; /* reserved */
|
||||
unsigned short alignment; /* alignment required */
|
||||
union name_pt name; /* index of subspace name */
|
||||
int fixup_request_index; /* index to first fixup */
|
||||
uint fixup_request_quantity; /* # of fixup requests */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Symbol Table
|
||||
//
|
||||
// The symbol table consists of a sequence of entries described by the structure
|
||||
// shown below, from <syms.h>. Strings for symbol and qualifier names are contained
|
||||
// in the symbol strings table, whose structure is identical with the space strings
|
||||
// table.
|
||||
|
||||
struct symbol_dictionary_record
|
||||
{
|
||||
unsigned char f1;
|
||||
#define SYM_F1_HIDDEN 0x80 /* symbol not visible to loader */
|
||||
#define SYM_F1_SECDEF 0x40 /* secondary def symbol */
|
||||
#define SYM_F1_TYPE 0x3F /* symbol type */
|
||||
bool hidden(void) { return (f1 & SYM_F1_HIDDEN) != 0; }
|
||||
bool secondary_def(void) { return (f1 & SYM_F1_SECDEF) != 0; }
|
||||
int symbol_type(void) { return (f1 & SYM_F1_TYPE); }
|
||||
|
||||
unsigned char f2;
|
||||
#define SYM_F2_SCOPE 0xF0 /* symbol value */
|
||||
#define SYM_F2_CHKLVL 0x0E /* type checking level */
|
||||
#define SYM_F2_MSTQUL 0x01 /* qualifier required */
|
||||
int symbol_scope(void) { return (f2 & SYM_F2_SCOPE ) >> 4; }
|
||||
int check_level(void) { return (f2 & SYM_F2_CHKLVL) >> 1; }
|
||||
bool must_qualify(void) { return (f2 & SYM_F2_MSTQUL) != 0; }
|
||||
|
||||
unsigned short f3;
|
||||
#define SYM_F3_FROZEN 0x8000 /* lock in memory when OS booted */
|
||||
#define SYM_F3_MEMRES 0x4000 /* lock in memory during exec */
|
||||
#define SYM_F3_ISCOM 0x2000 /* common block */
|
||||
#define SYM_F3_DUPCOM 0x1000 /* duplicate data symbols allowed */
|
||||
#define SYM_F3_XLEAST 0x0C00 /* MPE-only */
|
||||
#define SYM_F3_ARGREL 0x03FF /* parameter relocation bits */
|
||||
bool initially_frozen(void) { return (f3 & SYM_F3_FROZEN) != 0; }
|
||||
bool memory_resident(void) { return (f3 & SYM_F3_MEMRES) != 0; }
|
||||
bool is_common(void) { return (f3 & SYM_F3_ISCOM ) != 0; }
|
||||
bool dup_common(void) { return (f3 & SYM_F3_DUPCOM) != 0; }
|
||||
int xleast(void) { return (f3 & SYM_F3_XLEAST) >>10; }
|
||||
int arg_reloc(void) { return (f3 & SYM_F3_ARGREL); }
|
||||
|
||||
union name_pt name; /* index to symbol name */
|
||||
union name_pt qualifier_name; /* index to qual name */
|
||||
uint symbol_info; /* subspace index */
|
||||
uint symbol_value; /* symbol value */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
/* Values for symbol_type */
|
||||
#define ST_NULL 0 /* unused symbol entry */
|
||||
#define ST_ABSOLUTE 1 /* non-relocatable symbol */
|
||||
#define ST_DATA 2 /* initialized data symbol */
|
||||
#define ST_CODE 3 /* generic code symbol */
|
||||
#define ST_PRI_PROG 4 /* program entry point */
|
||||
#define ST_SEC_PROG 5 /* secondary prog entry point*/
|
||||
#define ST_ENTRY 6 /* procedure entry point */
|
||||
#define ST_STORAGE 7 /* storage request */
|
||||
#define ST_STUB 8 /* MPE-only */
|
||||
#define ST_MODULE 9 /* Pascal module name */
|
||||
#define ST_SYM_EXT 10 /* symbol extension record */
|
||||
#define ST_ARG_EXT 11 /* argument extension record */
|
||||
#define ST_MILLICODE 12 /* millicode entry point */
|
||||
#define ST_PLABEL 13 /* MPE-only */
|
||||
#define ST_OCT_DIS 14 /* Used by OCT only--ptr to translated code */
|
||||
#define ST_MILLI_EXT 15 /* address of external millicode */
|
||||
#define ST_TSTORAGE 16 /* TLS common symbol */
|
||||
|
||||
/* Values for symbol_scope */
|
||||
#define SS_UNSAT 0 /* unsatisfied reference */
|
||||
#define SS_EXTERNAL 1 /* import request to external symbol */
|
||||
#define SS_LOCAL 2 /* local symbol */
|
||||
#define SS_UNIVERSAL 3 /* global symbol */
|
||||
|
||||
// The meaning of the symbol value depends on the symbol type. For the code symbols
|
||||
// (generic code, program entry points, procedure and millicode entry points), the
|
||||
// low-order two bits of the symbol value encode the execution privilege level,
|
||||
// which is not used on HP-UX, but is generally set to 3. The symbol value with
|
||||
// those bits masked out is the address of the symbol (which is always a multiple
|
||||
// of 4). For data symbols, the symbol value is simply the address of the symbol.
|
||||
// For thread local storage symbols (not commons), the symbol value is the thread
|
||||
// local storage offset in a library or executable file, and is the size of the
|
||||
// symbol if in a relocatable object file. For storage requests and thread local
|
||||
// storage commons, the symbol value is the number of bytes requested; the linker
|
||||
// allocates space for the largest request for each symbol in the $BSS$ or $TBSS$
|
||||
// subspaces, unless a local or universal symbol is found for that symbol (in which
|
||||
// case the storage request is treated like an unsatisfied reference).
|
||||
//
|
||||
// If a relocatable file is compiled with parameter type checking, extension
|
||||
// records follow symbols that define and reference procedure entry points and
|
||||
// global variables. The first extension record, the symbol extension record,
|
||||
// defines the type of the return value or global variable, and (if a procedure or
|
||||
// function) the number of parameters and the types of the first three parameters.
|
||||
// If more parameter type descriptors are needed, one or more argument extension
|
||||
// records follow, each containing four more descriptors. A check level of 0
|
||||
// specifies no type checking; no extension records follow. A check level of 1 or
|
||||
// more specifies checking of the return value or global variable type. A check
|
||||
// level of 2 or more specifies checking of the number of parameters, and a check
|
||||
// level of 3 specifies checking the types of each individual parameter. The linker
|
||||
// performs the requested level of type checking between unsatisfied symbols and
|
||||
// local or universal symbols as it resolves symbol references.
|
||||
|
||||
union arg_descriptor
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint reserved: 3; /* reserved */
|
||||
uint packing: 1; /* packing algorithm used */
|
||||
uint alignment: 4; /* byte alignment */
|
||||
uint mode: 4; /* type of descriptor and its use */
|
||||
uint structure: 4; /* structure of symbol */
|
||||
uint hash: 1; /* set if arg_type is hashed */
|
||||
int arg_type: 15; /* data type */
|
||||
} arg_desc;
|
||||
uint word;
|
||||
};
|
||||
|
||||
struct symbol_extension_record
|
||||
{
|
||||
uint type: 8; /* always ST_SYM_EXT */
|
||||
uint max_num_args: 8; /* max # of parameters */
|
||||
uint min_num_args: 8; /* min # of parameters */
|
||||
uint num_args: 8; /* actual # of parameters */
|
||||
union arg_descriptor symbol_desc; /* symbol type desc. */
|
||||
union arg_descriptor argument_desc[3]; /* first 3 parameters */
|
||||
};
|
||||
|
||||
struct argument_desc_array
|
||||
{
|
||||
uint type: 8; /* always ST_ARG_EXT */
|
||||
uint reserved: 24; /* reserved */
|
||||
union arg_descriptor argument_desc[4]; /* next 4 parameters */
|
||||
};
|
||||
|
||||
// The alignment field in arg_descriptor indicates the minimum alignment of the
|
||||
// data, where a value of n represents 2^n byte alignment. The values for the mode,
|
||||
// structure, and arg_type (when the data type is not hashed) fields in
|
||||
// arg_descriptor are given in the following table.
|
||||
//
|
||||
// Value mode structure arg_type
|
||||
// 0 any any any
|
||||
// 1 value parm scalar void
|
||||
// 2 reference parm array signed byte
|
||||
// 3 value-result struct unsigned byte
|
||||
// 4 name pointer signed short
|
||||
// 5 variable int32 ptr unsigned short
|
||||
// 6 function return C string signed int32
|
||||
// 7 procedure Pascal string unsigned int32
|
||||
// 8 int32 ref parm procedure signed dbl word
|
||||
// 9 function unsigned dbl word
|
||||
// 10 label short real
|
||||
// 11 real
|
||||
// 12 int32 real
|
||||
// 13 short complex
|
||||
// 14 complex
|
||||
// 15 int32 complex
|
||||
// 16 packed decimal
|
||||
// 17 struct/array
|
||||
//
|
||||
//
|
||||
// For procedure entry points, the parameter relocation bits define the locations
|
||||
// of the formal parameters and the return value. Normally, the first four words of
|
||||
// the parameter list are passed in general registers (r26-r23) instead of on the
|
||||
// stack, and the return value is returned in r29. Floating-point parameters in
|
||||
// this range are passed instead in floating-point registers (fr4-fr7) and a
|
||||
// floating-point value is returned in fr4. The parameter relocation bits consist
|
||||
// of five pairs of bits that describe the first four words of the parameter list
|
||||
// and the return value. The leftmost pair of bits describes the first parameter
|
||||
// word, and the rightmost pair of bits describes the return value. The meanings of
|
||||
// these bits are shown in the following table.
|
||||
//
|
||||
// Bits Meaning
|
||||
// 00 No parameter or return value
|
||||
// 01 Parameter or return value in general register
|
||||
// 10 Parameter or return value in floating-point register
|
||||
// 11 Double-precision floating-point value
|
||||
//
|
||||
//
|
||||
// For double-precision floating-point parameters, the odd-numbered parameter word
|
||||
// should be marked 11 and the even-numbered parameter word should be marked 10.
|
||||
// Double-precision return values are simply marked 11.
|
||||
//
|
||||
// Every procedure call is tagged with a similar set of bits (see "Relocation
|
||||
// Information" below), so that the linker can match each call with the
|
||||
// expectations of the procedure entry point. If the call and entry point mismatch,
|
||||
// the linker creates a stub that relocates the parameters and return value as
|
||||
// appropriate.
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// DL header
|
||||
//
|
||||
// The DL header appears in every shared library and in incomplete executables (program
|
||||
// files linked with shared libraries--may contain unsatisfied symbols which will be satis-fied
|
||||
// at run time by the dynamic loader). It is assumed to be at offset 0 in the $TEXT$
|
||||
// space. It defines fields used by the dynamic loader and various other tools when attach-ing
|
||||
// the shared libraries at run time. The header contains information on the location of
|
||||
// the export and import lists, the module table, the linkage tables, as well as the sizes of
|
||||
// the tables.
|
||||
|
||||
|
||||
struct dl_header
|
||||
{
|
||||
int hdr_version; /* header version number */
|
||||
#define OLD_HDR_VERSION 89060912 // prior to 10.0
|
||||
#define HDR_VERSION 93092112
|
||||
int ltptr_value; /* data offset of LT pointer (R19) */
|
||||
int shlib_list_loc; /* text offset of shlib list */
|
||||
int shlib_list_count; /* count of items in shlib list */
|
||||
int import_list_loc; /* text offset of import list */
|
||||
int import_list_count; /* count of items in import list */
|
||||
int hash_table_loc; /* text offset of export hash table */
|
||||
int hash_table_size; /* count of slots in export hash table */
|
||||
int export_list_loc; /* text offset of export list */
|
||||
int export_list_count; /* count of items in export list */
|
||||
int string_table_loc; /* text offset of string table */
|
||||
int string_table_size; /* length in bytes of string table */
|
||||
int dreloc_loc; /* text offset of dynamic reloc records */
|
||||
int dreloc_count; /* number of dynamic relocation records */
|
||||
int dlt_loc; /* data offset of data linkage table */
|
||||
int plt_loc; /* data offset of procedure linkage table */
|
||||
int dlt_count; /* number of dlt entries in linkage table */
|
||||
int plt_count; /* number of plt entries in linkage table */
|
||||
short highwater_mark; /* highest version number seen in lib or in shlib list*/
|
||||
short flags; /* various flags */
|
||||
#define ELAB_DEFINED 1 /* an elaborator has been defined for this library */
|
||||
#define INIT_DEFINED 2 /* an initializer has been defined for this library */
|
||||
#define SHLIB_PATH_ENABLE 4 /* allow search of SHLIB_PATH at runtime */
|
||||
#define EMBED_PATH_ENABLE 8 /*allow search of embed path at runtime*/
|
||||
#define SHLIB_PATH_FIRST 16 /* search SHLIB_PATH first */
|
||||
#define SEARCH_ALL_STORS 32 /* search all shlibs to satisfy STOR import */
|
||||
#define SHLIB_INTERNAL_NAME 64 /*shlib has an internal name, for library-level versioning support*/
|
||||
int export_ext_loc; /* text offset of export extension tbl */
|
||||
int module_loc; /* text offset of module table*/
|
||||
int module_count; /* number of module entries */
|
||||
int elaborator; /* import index of elaborator */
|
||||
int initializer; /* import index of initializer */
|
||||
int embedded_path; /* index into string table for search path. index must be > 0 to be valid */
|
||||
int initializer_count; /* count of items in initializer import list*/
|
||||
int tdsize; /* size of the TSD area */
|
||||
int fastbind_list_loc; /* text-relative offset of fastbind info */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
// Import entry
|
||||
|
||||
struct import_entry // parallel with DLT followed by PLT
|
||||
{
|
||||
int name; /* offset in string table */
|
||||
short reserved2; /* unused */
|
||||
unsigned char type; /* symbol type */
|
||||
unsigned char flags;
|
||||
#define IMP_ENTRY_BYPASS 0x80 /* address of code symbol not taken in shlib */
|
||||
#define IMP_ENTRY_TPREL 0x40 /* new field*/
|
||||
bool bypassable(void) { return (flags & IMP_ENTRY_BYPASS) != 0; }
|
||||
bool is_tp_relative(void) { return (flags & IMP_ENTRY_TPREL ) != 0; }
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
// Export entry
|
||||
|
||||
struct misc_info
|
||||
{
|
||||
short version; /* months since January, 1990 */
|
||||
ushort flags;
|
||||
#define MISC_INFO_RELOC 0x3FF /* parameter relocation bits (5*2) */
|
||||
uint arg_reloc(void) { return flags & MISC_INFO_RELOC; }
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
struct export_entry
|
||||
{
|
||||
int next; /* index of next export entry in hash chain */
|
||||
int name; /* offset within string table */
|
||||
int value; /* offset of symbol (subject to relocation) */
|
||||
union
|
||||
{
|
||||
int size; /* storage request area size in bytes */
|
||||
struct misc_info misc; /* version, etc. N/A to storage requests */
|
||||
} info;
|
||||
unsigned char type; /* symbol type */
|
||||
unsigned char flags;
|
||||
#define EXP_ENTRY_TPREL 0x80 /* TLS export*/
|
||||
bool is_tp_relative(void) { return (flags & EXP_ENTRY_TPREL ) != 0; }
|
||||
short module_index; /* index of module defining this symbol */
|
||||
void swap(void);
|
||||
};
|
||||
|
||||
#endif // ifndef HPSOM_HPP
|
||||
14
idasdk76/ldr/hpsom/makefile
Normal file
14
idasdk76/ldr/hpsom/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=hpsom
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)hpsom$(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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \
|
||||
common.cpp hpsom.cpp hpsom.hpp
|
||||
212
idasdk76/ldr/idaldr.h
Normal file
212
idasdk76/ldr/idaldr.h
Normal file
@@ -0,0 +1,212 @@
|
||||
#ifndef __IDALDR_H__
|
||||
#define __IDALDR_H__
|
||||
|
||||
#include <ida.hpp>
|
||||
#include <fpro.h>
|
||||
#include <idp.hpp>
|
||||
#include <loader.hpp>
|
||||
#include <name.hpp>
|
||||
#include <bytes.hpp>
|
||||
#include <offset.hpp>
|
||||
#include <segment.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <fixup.hpp>
|
||||
#include <entry.hpp>
|
||||
#include <auto.hpp>
|
||||
#include <diskio.hpp>
|
||||
#include <kernwin.hpp>
|
||||
|
||||
//----------------------------------
|
||||
|
||||
#define CLASS_CODE "CODE"
|
||||
#define NAME_CODE ".text"
|
||||
#define CLASS_DATA "DATA"
|
||||
#define CLASS_CONST "CONST"
|
||||
#define NAME_DATA ".data"
|
||||
#define CLASS_BSS "BSS"
|
||||
#define NAME_BSS ".bss"
|
||||
#define NAME_EXTERN "extern"
|
||||
#define NAME_COMMON "common"
|
||||
#define NAME_ABS "abs"
|
||||
#define NAME_UNDEF "UNDEF"
|
||||
#define CLASS_STACK "STACK"
|
||||
#define CLASS_RES16 "RESOURCE"
|
||||
#define LDR_NODE "$ IDALDR node for ids loading $"
|
||||
#define LDR_INFO_NODE "$ IDALDR node for unload $"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
template <class T> bool _validate_array_count(
|
||||
linput_t *li,
|
||||
T *p_cnt,
|
||||
size_t elsize,
|
||||
int64 current_offset=-1,
|
||||
int64 max_offset=-1)
|
||||
{
|
||||
if ( current_offset == -1 )
|
||||
current_offset = qltell(li);
|
||||
if ( max_offset == -1 )
|
||||
max_offset = qlsize(li);
|
||||
int64 rest = max_offset - current_offset;
|
||||
T cnt = *p_cnt;
|
||||
if ( current_offset >= 0 && rest >= 0 )
|
||||
{
|
||||
#ifndef __X86__
|
||||
typedef size_t biggest_t;
|
||||
#else
|
||||
typedef ea_t biggest_t;
|
||||
#endif
|
||||
if ( is_mul_ok<biggest_t>(elsize, cnt) )
|
||||
{
|
||||
biggest_t needed = elsize * cnt;
|
||||
#ifdef __X86__
|
||||
if ( needed == size_t(needed) )
|
||||
#endif
|
||||
if ( rest >= needed )
|
||||
return true; // all ok
|
||||
}
|
||||
cnt = rest / elsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
cnt = 0;
|
||||
}
|
||||
*p_cnt = cnt;
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Validate a counter taken from the input file. If there are not enough bytes
|
||||
// in the input file, ask the user if we may continue and fix the counter.
|
||||
template <class T> void validate_array_count(
|
||||
linput_t *li,
|
||||
T *p_cnt,
|
||||
size_t elsize,
|
||||
const char *counter_name,
|
||||
int64 curoff=-1,
|
||||
int64 maxoff=-1)
|
||||
{
|
||||
T old = *p_cnt;
|
||||
if ( !_validate_array_count(li, p_cnt, elsize, curoff, maxoff) )
|
||||
{
|
||||
static const char *const format =
|
||||
"AUTOHIDE SESSION\n"
|
||||
"HIDECANCEL\n"
|
||||
"%s %" FMT_64 "u is incorrect, maximum possible value is %" FMT_64 "u%s";
|
||||
#ifndef __KERNEL__
|
||||
if ( ask_yn(ASKBTN_YES,
|
||||
format,
|
||||
counter_name,
|
||||
uint64(old),
|
||||
uint64(*p_cnt),
|
||||
". Do you want to continue with the new value?") != ASKBTN_YES )
|
||||
{
|
||||
loader_failure(NULL);
|
||||
}
|
||||
#else
|
||||
warning(format, counter_name, uint64(old), uint64(*p_cnt), "");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Validate a counter taken from the input file. If there are not enough bytes
|
||||
// in the input file, die.
|
||||
template <class T> void validate_array_count_or_die(
|
||||
linput_t *li,
|
||||
T cnt,
|
||||
size_t elsize,
|
||||
const char *counter_name,
|
||||
int64 curoff=-1,
|
||||
int64 maxoff=-1)
|
||||
{
|
||||
if ( !_validate_array_count(li, &cnt, elsize, curoff, maxoff) )
|
||||
{
|
||||
static const char *const format =
|
||||
"%s is incorrect, maximum possible value is %u%s";
|
||||
#ifndef __KERNEL__
|
||||
loader_failure(format, counter_name, uint(cnt), "");
|
||||
#else
|
||||
error(format, counter_name, uint(cnt), "");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Read a string table in COFF format.
|
||||
inline bool read_string_table(qstring *out, linput_t *li, qoff64_t filepos=0, bool mf=false)
|
||||
{
|
||||
if ( filepos != 0 && qlseek(li, filepos, SEEK_SET) != filepos )
|
||||
return false;
|
||||
// read the string table length
|
||||
uint32 strtsize;
|
||||
if ( qlread(li, &strtsize, 4) != 4 )
|
||||
return false;
|
||||
if ( mf )
|
||||
strtsize = swap32(strtsize);
|
||||
|
||||
// it includes the length field itself, so should be greater than 4
|
||||
if ( strtsize <= 4 )
|
||||
return false; // too small table
|
||||
|
||||
qlseek(li, -4, SEEK_CUR);
|
||||
#ifdef LOADER_COMPILE
|
||||
// Loaders display a message about the problematic size, to inform the user
|
||||
// and give him a choice.
|
||||
validate_array_count(li, &strtsize, 1, "String table size");
|
||||
#else
|
||||
// Other modules silently fail.
|
||||
if ( !_validate_array_count(li, &strtsize, 1) )
|
||||
return false;
|
||||
#endif
|
||||
|
||||
char *stable = (char *)qalloc(strtsize + 1);
|
||||
if ( stable == NULL )
|
||||
return false; // out of memory?!
|
||||
|
||||
bool ok;
|
||||
if ( qlread(li, stable, strtsize) == strtsize )
|
||||
{
|
||||
stable[strtsize] = '\0';
|
||||
out->clear();
|
||||
out->inject(stable, strtsize + 1);
|
||||
ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
qfree(stable);
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline uchar readchar(linput_t *li)
|
||||
{
|
||||
uchar x;
|
||||
lread(li, &x, sizeof(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline uint16 readshort(linput_t *li)
|
||||
{
|
||||
uint16 x;
|
||||
lread(li, &x, sizeof(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline uint32 readlong(linput_t *li)
|
||||
{
|
||||
uint32 x;
|
||||
lread(li, &x, sizeof(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
inline uint32 mf_readlong(linput_t *li) { return swap32(readlong(li)); }
|
||||
inline uint16 mf_readshort(linput_t *li) { return swap16(readshort(li)); }
|
||||
|
||||
// each loader must declare and export this symbol:
|
||||
idaman loader_t ida_module_data LDSC;
|
||||
|
||||
#endif // __IDALDR_H__
|
||||
46
idasdk76/ldr/intelomf/common.cpp
Normal file
46
idasdk76/ldr/intelomf/common.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
bool is_intelomf_file(linput_t *li)
|
||||
{
|
||||
uchar magic;
|
||||
lmh h;
|
||||
qlseek(li, 0);
|
||||
if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic)
|
||||
|| qlread(li, &h, sizeof(h)) != sizeof(h) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int64 fsize = qlsize(li);
|
||||
return magic == INTELOMF_MAGIC_BYTE
|
||||
&& h.tot_length < fsize;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static int read_pstring(linput_t *li, char *name, int size)
|
||||
{
|
||||
char buf[256];
|
||||
uchar nlen;
|
||||
lread(li, &nlen, sizeof(nlen));
|
||||
lread(li, buf, nlen);
|
||||
buf[nlen] = '\0';
|
||||
qstrncpy(name, buf, size);
|
||||
return nlen;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static uint32 readdw(const uchar *&ptr, bool wide)
|
||||
{
|
||||
uint32 x;
|
||||
if ( wide )
|
||||
{
|
||||
x = *(uint32 *)ptr;
|
||||
ptr += sizeof(uint32);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = *(uint16 *)ptr;
|
||||
ptr += sizeof(uint16);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
397
idasdk76/ldr/intelomf/intelomf.hpp
Normal file
397
idasdk76/ldr/intelomf/intelomf.hpp
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 4.20
|
||||
* Copyright (c) 2002 by Ilfak Guilfanov. (ig@datarescue.com)
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Intel OMF386
|
||||
//
|
||||
|
||||
#ifndef INTELOMF_HPP
|
||||
#define INTELOMF_HPP
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define INTELOMF_MAGIC_BYTE 0xB0 // The first byte of the file
|
||||
// must have this value
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Linkable Module Header
|
||||
// A linkable object file contains one or more linkable modules
|
||||
//-----------------------------------------------------------------------
|
||||
struct lmh /* linkable module header */
|
||||
{
|
||||
uint32 tot_length; /* total length of the module on disk in bytes */
|
||||
int16 num_segs; /* number of SEGDEF sections in the module */
|
||||
int16 num_gates; /* number of GATDEF sections in the module */
|
||||
int16 num_publics; /* number of PUBDEF sections in the module */
|
||||
int16 num_externals; /* number of EXTDEF sections in the module */
|
||||
char linked; /* linked = 0, if the module was produced by a translator */
|
||||
char date[8]; /* the creation date, written in the form MM/DD/YY */
|
||||
char time[8]; /* the creation time, written in the form HH:MM:SS */
|
||||
char mod_name[41]; /* name of the module, the first char is the string's length */
|
||||
char creator[41]; /* the name of the program which created the module */
|
||||
char src_path[46]; /* the path to the source file which produced the module */
|
||||
char trans_id; /* translator id, mainly for debugger */
|
||||
char trans_vers[4]; /* translator version (ASCII) */
|
||||
char OMF_vers; /* OMF version */
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct toc_p1 /* Table of contents for first partition */
|
||||
{
|
||||
int32 SEGDEF_loc; /* all the following _loc represents location of the first byte */
|
||||
int32 SEGDEF_len; /* of the section in current module, unit is byte; */
|
||||
int32 GATDEF_loc; /* all the following _len represents the length of the section */
|
||||
int32 GATDEF_len; /* also the unit is byte. */
|
||||
int32 TYPDEF_loc;
|
||||
int32 TYPDEF_len;
|
||||
int32 PUBDEF_loc;
|
||||
int32 PUBDEF_len;
|
||||
int32 EXTDEF_loc;
|
||||
int32 EXTDEF_len;
|
||||
int32 TXTFIX_loc;
|
||||
int32 TXTFIX_len;
|
||||
int32 REGINT_loc;
|
||||
int32 REGINT_len;
|
||||
int32 next_partition;
|
||||
int32 reserved;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
struct segdef /* segment definition */
|
||||
{
|
||||
int16 attributes; /* need to be separated into bits to get bitwise info(cf. [1]) */
|
||||
int32 slimit; /* the length of the segment minus one, in bytes */
|
||||
int32 dlength; /* the number of data bytes in the segment, only for dsc seg*/
|
||||
int32 speclength; /* the total number of bytes in the segment */
|
||||
int16 ldt_position; /* the position in LDT that this segment must occupy */
|
||||
char align; /* alignment requirements of the segment */
|
||||
char combine_name[41]; /* first char is the length of the string in byte,
|
||||
rest is name */
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// The GATDEF section defines an entry for each gate occurring in the module.
|
||||
// There is a 1-byte field in the data structure which is used to identify type
|
||||
// of gate from call gate, task gate, interrupt gate or trap gate. (cf. [1])
|
||||
|
||||
struct gatdef /* Gate definition */
|
||||
{
|
||||
char privilege; /* privilege of gate */
|
||||
char present;
|
||||
char gate_type;
|
||||
int32 GA_offset; /* gate entry GA consists of GA_offset and GA_segment */
|
||||
int16 GA_segment;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// The TYPDEF section serves two purposes: to allow Relocation and Linkage
|
||||
// software to check the validity of sharing data across external linkages,
|
||||
// and to provide type information to debuggers to interpret data correct.
|
||||
// [2] provides storage size equivalence tables and lists the syntactical
|
||||
// constructs for high level languages PL/M, PASCAL, FORTRAN and C.
|
||||
|
||||
struct leaf
|
||||
{
|
||||
char type; /* an 8-bit number defines the type of the leaf */
|
||||
union /* following are different kind of leaves */
|
||||
{
|
||||
char *string;
|
||||
int16 num_2;
|
||||
int32 num_4;
|
||||
uint64 num_8;
|
||||
int64 s_8;
|
||||
int16 s_2;
|
||||
int32 s_4;
|
||||
} content;
|
||||
struct leaf *next; /* points to next leaf */
|
||||
};
|
||||
|
||||
struct typdef /* type definition */
|
||||
{
|
||||
char linkage; /* is TRUE, if for public-external linkage; is FALSE, if only for debug symbols. */
|
||||
int16 length; /* the length in bytes of all the leaves in it */
|
||||
struct leaf leaves; /* all different leaves format */
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// PUBDEF section contains a list of public names with their general
|
||||
// addresses for the public symbols. The 2-byte field type_IN specifies
|
||||
// an internal name for a segment, gate, GDT selector or the special
|
||||
// CONST$IN. This section serves to define symbols to be exported to
|
||||
// other modules.
|
||||
|
||||
struct pubdef /* public definition */
|
||||
{
|
||||
int32 PUB_offset; /* gen addr consists of PUB_offset and PUB_segment */
|
||||
int16 PUB_segment;
|
||||
int16 type_IN; /* internal name for the type of the public of symbol */
|
||||
char wordcount; /* the total # of 16-bit entities of stacked parameters */
|
||||
char sym_name[256];
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// EXTDEF section lists all external symbols, which are then referenced
|
||||
// elsewhere in the module by means of their internal name. The 2-byte
|
||||
// field seg_IN specifies the segment that is assumed to contain the
|
||||
// matching public symbol and the 2-byte value of type_IN defines the
|
||||
// type of the external symbol. (cf. [1])
|
||||
|
||||
struct extdef /* external definition */
|
||||
{
|
||||
int16 seg_IN; /* internal name of segment having matched public symbol */
|
||||
int16 type_IN; /* internal name for the type of the external symbol */
|
||||
char allocate; /* not zero, if R&L needs allocate space for external symbol*/
|
||||
union
|
||||
{
|
||||
int16 len_2;
|
||||
int32 len_4;
|
||||
} allocate_len; /* number of bytes needed allocated for the external symbol */
|
||||
char sym_name[256]; /* the 1st char is length , the rest are name of the symbol*/
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// text block contains binaries for code segment and data segment.
|
||||
// These segments are relocatable. Other than that, all the SLD information
|
||||
// is also implemented in this block by a translator under debug option.
|
||||
// Segment MODULES in the text block is designed with the purpose of
|
||||
// providing general information about the current module. Segment MBOLS
|
||||
// provides entries for each symbol used in the module, including stack
|
||||
// symbols, local symbols and symbols that are used as procedure or block
|
||||
// start entries. Segment LINES consists of line offset values, each line
|
||||
// offset is the byte offset of the start of a line in the code segment.
|
||||
// Segment SRCLINES consists of line offsets of the source files.
|
||||
|
||||
struct mod /* MODULES segment */
|
||||
{
|
||||
int16 ldt_sel; /* a selector into the GDT for an LDT which contains the segments in this module */
|
||||
int32 code_offset; /* code segment GA consists of code_offset and code_IN */
|
||||
int16 code_IN;
|
||||
int32 types_offset; /* TYPES GA consists of types_offset and types_IN */
|
||||
int16 types_IN;
|
||||
int32 sym_offset; /* MBOLS GA consists of sym_coffset and sym_IN */
|
||||
int16 sym_IN;
|
||||
int32 lines_offset; /* LINES GA consists of lines_offset and lines_IN */
|
||||
int16 lines_IN;
|
||||
int32 pub_offset; /* PUBLICS GA consists of pub_offset and pub_IN */
|
||||
int16 pub_IN;
|
||||
int32 ext_offset; /* EXTERNAL GA consists of ext_offset and ext_IN */
|
||||
int16 ext_IN;
|
||||
int32 src_offset; /* SRCLINES GA consists of src_offset and src_IN */
|
||||
int16 src_IN;
|
||||
int16 first_line; /* first line number */
|
||||
char kind; /* 0 value for 286, 1 value for 386 format */
|
||||
char trans_id; /* same as lmh */
|
||||
char trans_vers[4]; /* same as lmh */
|
||||
char *mod_name; /* same as lmh */
|
||||
};
|
||||
|
||||
struct blk /* block start entry */
|
||||
{
|
||||
int32 offset; /* offset in code segment */
|
||||
int32 blk_len; /* block length */
|
||||
char *blk_name; /* block name, note that first byte is the length of string */
|
||||
};
|
||||
|
||||
struct proc /* procedure start entry */
|
||||
{
|
||||
int32 offset; /* offset in code segment */
|
||||
int16 type_IN; /* internal name of the typdef associated with the proc */
|
||||
char kind; /* specifying 16-bit or 32-bit */
|
||||
int32 ebp_offset; /* offset of return address from EBP */
|
||||
int32 proc_len; /* procedure length */
|
||||
char *proc_name; /* procedure name, as always, the 1st char is string length */
|
||||
};
|
||||
|
||||
struct sbase /* symbol base entry */
|
||||
{
|
||||
int32 offset;
|
||||
int16 s_IN;
|
||||
};
|
||||
|
||||
struct symbol /* symbol entry */
|
||||
{
|
||||
int32 offset;
|
||||
int16 type_IN;
|
||||
char *sym_name;
|
||||
};
|
||||
|
||||
struct sym /* MBOLS segment */
|
||||
{
|
||||
char kind; /* kind of entries */
|
||||
union
|
||||
{
|
||||
struct blk blk_start; /* block start entry */
|
||||
struct proc prc_start; /* procedure start entry */
|
||||
struct sbase sym_base; /* symbol base entry */
|
||||
struct symbol s_ent; /* symbol entry */
|
||||
} entry;
|
||||
struct sym *next;
|
||||
};
|
||||
|
||||
struct line /* LINES segment */
|
||||
{
|
||||
int32 offset;
|
||||
struct lines *next;
|
||||
};
|
||||
|
||||
struct src /* SRCLINES segment */
|
||||
{
|
||||
char *src_file; /* source file name */
|
||||
int16 count;
|
||||
struct lines *src_line;
|
||||
struct srclines *next;
|
||||
};
|
||||
|
||||
struct text /* text block */
|
||||
{
|
||||
int32 txt_offset; /* gen addr consists of txt_offset and txt_IN */
|
||||
int16 txt_IN; /* internal segment name */
|
||||
int32 length; /* the length of the text content, in byte */
|
||||
union
|
||||
{
|
||||
char *code; /* CODE segment */
|
||||
char *data; /* DATA segment */
|
||||
struct mod modules; /* MODULES segment */
|
||||
struct sym symbols; /* MBOLS segment */
|
||||
struct line lines; /* LINES segment */
|
||||
struct src srclines;/* SRCLINES segment */
|
||||
} segment;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// block contains information that allows the binder or linker to resolve
|
||||
// (fix up) and eventually relocate references between object modules.
|
||||
// The attributes where_IN and where_offset in the following data structures
|
||||
// make a generalized address specifying the target for the fixup. Similarly,
|
||||
// the attributes what_IN and what_offset make a generalized address
|
||||
// specifying the target to which the fixup is to be applied.
|
||||
|
||||
// There are four kinds of fixups for Intel linkable object modules.
|
||||
// They are:
|
||||
// general fixup,
|
||||
// intra-segment fixup,
|
||||
// call fixup
|
||||
// addition fixup.
|
||||
// The general fixup and the addition fixup have the same data structure,
|
||||
// both provide general addresses for where_IN, where_offset, and what_IN,
|
||||
// what_offset. The intra-segment fixup is equivalent to a general fixup
|
||||
// with what_IN = where_IN, and the call fixup is also equivalent to a
|
||||
// general fixup with what_offset = 0. (cf. [1])
|
||||
|
||||
struct gen /* for general fixup */
|
||||
{
|
||||
char kind; /* specifying the kind of fixup */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} where_offset; /* 2- or 4- byte where_offset */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} what_offset; /* 2- or 4- byte what_offset */
|
||||
int16 what_IN; /* what_IN & what_offset specify the target for the fixup*/
|
||||
union fixups *next;
|
||||
};
|
||||
|
||||
struct intra /* for intra-segment fixup */
|
||||
{
|
||||
char kind; /* specifying the kind of fixup */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} where_offset; /* 2- or 4- byte where_offset */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} what_offset; /* 2- or 4- byte what_offset */
|
||||
union fixups *next;
|
||||
};
|
||||
|
||||
struct cal /* for call fixup */
|
||||
{
|
||||
char kind; /* specifying the kind of fixup */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} where_offset; /* 2- or 4- byte where-offset */
|
||||
int16 what_IN;
|
||||
union fixups *next;
|
||||
};
|
||||
|
||||
struct ad /* for addition fixup */
|
||||
{
|
||||
char kind; /* specifying the kind of fixup */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} where_offset; /* specifying the target to which the fixup is to be applied */
|
||||
union
|
||||
{
|
||||
int16 num2;
|
||||
int32 num4;
|
||||
} what_offset;
|
||||
int16 what_IN;
|
||||
union fixups *next;
|
||||
};
|
||||
|
||||
struct temp /* for the text template in the iterated text block */
|
||||
{
|
||||
int32 length; /* the length, in bytes, of a single mem blk to be initialized */
|
||||
char *value; /* the text or data to be used to initialize any single mem blk*/
|
||||
};
|
||||
|
||||
struct iterat /* for iterated text block */
|
||||
{
|
||||
int32 it_offset;
|
||||
int16 it_segment; /* above two specify a gen addr to put 1st byte of the text */
|
||||
int32 it_count; /* the # of times the text template is to be repeated */
|
||||
struct temp text; /* the text template */
|
||||
};
|
||||
|
||||
struct fixup /* fixup block */
|
||||
{
|
||||
int16 where_IN; /* specifying the segment to which fixups should be applied*/
|
||||
int16 length; /* the length in bytes of the fixups */
|
||||
union
|
||||
{
|
||||
struct gen general; /* for general fixup */
|
||||
struct intra in_seg; /* for intra-segment fixup */
|
||||
struct cal call_fix; /* call fixup */
|
||||
struct ad addition; /* addition fixup */
|
||||
} fixups;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// The TXTFIX section consists of intermixed text block, fixup block and
|
||||
// iterated text block. As one can see, it is the TXTFIX section that
|
||||
// records the binaries for machine codes, initialized data and
|
||||
// uninitialized data. TXTFIX section output by a translator under debug
|
||||
// option will also contain SLD information.
|
||||
|
||||
struct txtfix /* text, iterated text and fixup block */
|
||||
{
|
||||
char blk_type; /* 0 for text blk; 1 for fixup blk and 2 for iterated text blk */
|
||||
union
|
||||
{
|
||||
struct text text_blk; /* text block */
|
||||
struct fixup fixup_blk; /* fixup block */
|
||||
struct iterat it_text_blk; /* iterated text block */
|
||||
} block;
|
||||
struct txtfix *next;
|
||||
};
|
||||
|
||||
// The file ends with a checksum byte
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
14
idasdk76/ldr/intelomf/makefile
Normal file
14
idasdk76/ldr/intelomf/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=intelomf
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)intelomf$(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 ../idaldr.h common.cpp intelomf.cpp \
|
||||
intelomf.hpp
|
||||
108
idasdk76/ldr/javaldr/javaldr.cpp
Normal file
108
idasdk76/ldr/javaldr/javaldr.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA)
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
* Java Virtual Machine pseudo-loader.
|
||||
* Copyright (c) 1995-2006 by Iouri Kharon.
|
||||
* E-mail: yjh@styx.cabel.net
|
||||
*
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
L O A D E R for Java-classFile
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "../../module/java/classfil.hpp"
|
||||
#include "../../module/java/notify_codes.hpp"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *)
|
||||
{
|
||||
uint32 magic;
|
||||
uint16 min_ver, maj_ver;
|
||||
|
||||
if ( lread4bytes(li, &magic, 1) != 0
|
||||
|| magic != MAGICNUMBER
|
||||
|| lread2bytes(li, &min_ver, 1) != 0
|
||||
|| lread2bytes(li, &maj_ver, 1) != 0 )
|
||||
{
|
||||
goto BADFMT;
|
||||
}
|
||||
|
||||
uchar jdk;
|
||||
if ( maj_ver <= JDK_MIN_MAJOR )
|
||||
{
|
||||
if ( maj_ver < JDK_MIN_MAJOR )
|
||||
goto BADFMT;
|
||||
jdk = maj_ver >= JDK_1_1_MINOR; //-V547 'maj_ver >= 3' is always true
|
||||
}
|
||||
else if ( maj_ver > JDK_MAX_MAJOR )
|
||||
{
|
||||
BADFMT:
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
jdk = (uchar)(maj_ver - (JDK_MIN_MAJOR-1));
|
||||
}
|
||||
|
||||
fileformatname->sprnt("JavaVM Class File (JDK 1.%u%s)",
|
||||
jdk,
|
||||
jdk == 3 ? "/CLDC" : "");
|
||||
*processor = "java";
|
||||
return f_LOADER;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
static void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/)
|
||||
{
|
||||
set_processor_type("java", SETPROC_LOADER);
|
||||
|
||||
if ( !java_module_t::load_file(li, (neflag & NEF_LOPT) != 0) )
|
||||
INTERR(20047);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
15
idasdk76/ldr/javaldr/makefile
Normal file
15
idasdk76/ldr/javaldr/makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
PROC=javaldr
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)javaldr$(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/java/classfil.hpp \
|
||||
../../module/java/notify_codes.hpp ../idaldr.h \
|
||||
javaldr.cpp
|
||||
15
idasdk76/ldr/loader.mak
Normal file
15
idasdk76/ldr/loader.mak
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
__FUZZ_LOADERS__=1
|
||||
|
||||
SRC_PATH = $(IDA)ldr/
|
||||
BIN_PATH = $(R)loaders/
|
||||
|
||||
BASE_OBJS += $(F)$(PROC)$(O)
|
||||
|
||||
ifdef __NT__
|
||||
DLLFLAGS += /BASE:0x140000000
|
||||
endif
|
||||
|
||||
CC_DEFS += LOADER_COMPILE
|
||||
|
||||
include ../../module.mak
|
||||
39
idasdk76/ldr/makefile
Normal file
39
idasdk76/ldr/makefile
Normal file
@@ -0,0 +1,39 @@
|
||||
include ../allmake.mak
|
||||
|
||||
GOALS += loaders
|
||||
.PHONY: $(GOALS)
|
||||
all: $(GOALS)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
ALLDIRS += aif
|
||||
ALLDIRS += amiga
|
||||
ALLDIRS += aof
|
||||
ALLDIRS += aout
|
||||
ALLDIRS += dos
|
||||
ALLDIRS += dump
|
||||
ALLDIRS += geos
|
||||
ALLDIRS += hex
|
||||
ALLDIRS += intelomf
|
||||
ALLDIRS += mas
|
||||
ALLDIRS += nlm
|
||||
ALLDIRS += pef
|
||||
ALLDIRS += pilot
|
||||
ALLDIRS += qnx
|
||||
ALLDIRS += script_ldrs
|
||||
ALLDIRS += w32run
|
||||
ALLDIRS-$(IDAADV) += hpsom
|
||||
ALLDIRS-$(IDAADV) += javaldr
|
||||
ALLDIRS-$(IDAADV) += os9
|
||||
ALLDIRS-$(IDAADV) += rt11
|
||||
ALLDIRS-$(IDAADV) += snes
|
||||
ALLDIRS += $(ALLDIRS-1)
|
||||
loaders: $(ALLDIRS)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
.PHONY: $(ALLDIRS)
|
||||
$(ALLDIRS):
|
||||
$(Q)$(MAKE) -C $@
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
clean::
|
||||
$(foreach dir,$(ALLDIRS),$(MAKE) -C $(dir) clean;)
|
||||
13
idasdk76/ldr/mas/makefile
Normal file
13
idasdk76/ldr/mas/makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
PROC=mas
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)mas$(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 ../idaldr.h mas.cpp mas.hpp
|
||||
407
idasdk76/ldr/mas/mas.cpp
Normal file
407
idasdk76/ldr/mas/mas.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
|
||||
// Loader for the Macro-assembler-related binary format
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "mas.hpp"
|
||||
|
||||
// undefine this to print some debugging information
|
||||
// in the IDA console.
|
||||
//#define DEBUG
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct gas_family
|
||||
{
|
||||
uchar code;
|
||||
const char *processor; //lint !e958 padding is required to align members
|
||||
};
|
||||
|
||||
static const struct gas_family families[] =
|
||||
{
|
||||
{ 0x01, "68k" },
|
||||
// 0x03 : M*Core
|
||||
{ 0x05, "ppc" },
|
||||
{ 0x09, "dsp56k" },
|
||||
{ 0x11, "m740" },
|
||||
// 0x12 : MELPS-4500
|
||||
// 0x13 : M16
|
||||
// 0x14 : M16C
|
||||
// 0x15 : F2MC8L
|
||||
{ 0x16, "f2mc16l" },
|
||||
{ 0x19, "m7700" },
|
||||
// 0x21 : MCS-48
|
||||
// 0x25 : SYM53C8xx
|
||||
// 0x29 : 29xxx
|
||||
{ 0x2A, "i960b" }, // little or big endian ????
|
||||
// 0x31 : MCS-51
|
||||
{ 0x32, "st9" },
|
||||
{ 0x33, "st7" },
|
||||
// 0x38 : 1802/1805
|
||||
// 0x39 : MCS-96/196/296
|
||||
// 0x3A : 8X30x
|
||||
{ 0x3B, "avr" },
|
||||
// 0x3C : XA
|
||||
// 0x3F : 4004/4040
|
||||
{ 0x41, "8085" },
|
||||
{ 0x42, "8086" },
|
||||
{ 0x47, "tms320c6" },
|
||||
// 0x48 : TMS9900
|
||||
// 0x49 : TMS370xxx
|
||||
// 0x4A : MSP430
|
||||
{ 0x4B, "tms32054" },
|
||||
{ 0x4C, "c166" },
|
||||
{ 0x51, "z80" },
|
||||
// 0x52 : TLCS-900
|
||||
// 0x53 : TLCS-90
|
||||
// 0x54 : TLCS-870
|
||||
// 0x55 : TLCS-47
|
||||
// 0x56 : TLCS-9000
|
||||
{ 0x61, "6800" },
|
||||
{ 0x62, "6805" },
|
||||
{ 0x63, "6809" },
|
||||
// 0x64 : 6804
|
||||
// 0x65 : 68HC16
|
||||
// 0x66 : 68HC12
|
||||
// 0x67 : ACE
|
||||
{ 0x68, "h8300" },
|
||||
{ 0x69, "h8500" },
|
||||
// 0x6C : SH7000
|
||||
// 0x6C : SC14xxx
|
||||
// 0x6C : SC/MP
|
||||
// 0x6C : COP8
|
||||
{ 0x70, "pic16cxx" },
|
||||
{ 0x71, "pic16cxx" },
|
||||
// 0x72 : PIC17C4x
|
||||
// 0x73 : TMS-7000
|
||||
// 0x74 : TSM3201x
|
||||
// 0x75 : TSM320C2x
|
||||
// 0x76 : TSM320C3x
|
||||
{ 0x77, "tms320c2" },
|
||||
// 0x78 : ST6uPD772
|
||||
{ 0x79, "z8" }
|
||||
// 0x7A : uPD78(C)10
|
||||
// 0x7B : 75K0
|
||||
// 0x7C : 78K0
|
||||
// 0x7D : uPD7720
|
||||
// 0x7E : uPD7725
|
||||
// 0x7F : uPD77230
|
||||
};
|
||||
|
||||
static char creator[MAXSTR]; // program name which created the binary
|
||||
static int entry_point; // address of the entry point
|
||||
static const char *set_proc = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// output an error and exit loader.
|
||||
AS_PRINTF(1, 2) NORETURN static void mas_error(const char *format, ...)
|
||||
{
|
||||
char b[MAXSTR];
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
qvsnprintf(b, sizeof(b), format, va);
|
||||
va_end(va);
|
||||
loader_failure("mas loader critical error: %s", b);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// set the current processor type according to "cpu_type".
|
||||
static bool mas_set_cpu(uchar cpu_type)
|
||||
{
|
||||
for ( int i = 0; i < qnumber(families); i++ )
|
||||
{
|
||||
if ( families[i].code != cpu_type )
|
||||
continue;
|
||||
|
||||
const char *proc = families[i].processor;
|
||||
if ( set_proc != NULL && !streq(proc, set_proc) )
|
||||
mas_error("only one processor record is allowed");
|
||||
|
||||
set_proc = proc;
|
||||
set_processor_type(proc, SETPROC_LOADER);
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: detected processor %s\n", proc);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// return a segment name according to its "segment_type".
|
||||
static const char *mas_get_segname(uchar segment_type)
|
||||
{
|
||||
switch ( segment_type )
|
||||
{
|
||||
case 0x00: return "UNDEFINED";
|
||||
case 0x01: return "CODE";
|
||||
case 0x02: return "DATA";
|
||||
case 0x03: return "IDATA";
|
||||
case 0x04: return "XDATA";
|
||||
case 0x05: return "YDATA";
|
||||
case 0x06: return "BDATA";
|
||||
case 0x07: return "IO";
|
||||
case 0x08: return "REG";
|
||||
case 0x09: return "ROMDATA";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// write comments.
|
||||
static void mas_write_comments(void)
|
||||
{
|
||||
create_filename_cmt();
|
||||
|
||||
char entry_point_str[20];
|
||||
if ( entry_point == -1 )
|
||||
qstrncpy(entry_point_str, "NOT DETECTED", sizeof(entry_point_str));
|
||||
else
|
||||
qsnprintf(entry_point_str, sizeof(entry_point_str), "0x%X", entry_point);
|
||||
|
||||
// write name of the creator program
|
||||
add_pgm_cmt("Creator program : %s", creator);
|
||||
// write address of the entry point
|
||||
add_pgm_cmt("Entry point : %s", entry_point_str);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// detect macro assembler files using the start sequence.
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *, // too difficult to determine the processor
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
// read the first word
|
||||
uint16 word = 0;
|
||||
if ( qlread(li, &word, 2) != 2 )
|
||||
return 0;
|
||||
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: 2 first bytes : 0x%X\n", word);
|
||||
#endif
|
||||
|
||||
// first word must match the start_sequence
|
||||
if ( word != START_SEQUENCE )
|
||||
return 0;
|
||||
|
||||
*fileformatname = "Macro Assembler by Alfred Arnold";
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: detected mas binary file !\n");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void load_bytes(linput_t *li, ea_t ea, asize_t size, const char *segname)
|
||||
{
|
||||
// validate the segment size
|
||||
ea_t end = ea + size;
|
||||
qoff64_t curpos = qltell(li);
|
||||
qoff64_t endpos = curpos + size;
|
||||
if ( ea == BADADDR || end < ea || endpos < curpos || endpos > qlsize(li) )
|
||||
mas_error("wrong or too big segment %a..%a", ea, end);
|
||||
|
||||
// send code in the database
|
||||
file2base(li, curpos, ea, end, FILEREG_PATCHABLE);
|
||||
|
||||
// set selector
|
||||
sel_t selector = allocate_selector(0);
|
||||
|
||||
// create data segment
|
||||
add_segm(selector, ea, end, segname, segname, ADDSEG_SPARSE);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
static void check_target_processor()
|
||||
{
|
||||
if ( PH.id == -1 )
|
||||
loader_failure("Failed to determine the target processor, please specify it manually");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// process a file record according to its "record_type".
|
||||
// return true if there is no more records to process.
|
||||
static bool process_record(linput_t *li, const uchar record_type, bool load)
|
||||
{
|
||||
bool finished = false;
|
||||
|
||||
switch ( record_type )
|
||||
{
|
||||
// A record with a header byte of $81 is a record that may contain code or
|
||||
// data from arbitrary segments.
|
||||
//
|
||||
// header : 1 byte
|
||||
// segment : 1 byte
|
||||
// gran : 1 byte
|
||||
// start_addr : 4 bytes (entry point)
|
||||
// length : 2 bytes
|
||||
// data : length bytes
|
||||
case 0x81:
|
||||
{
|
||||
mas_header_t header;
|
||||
memset(&header, 0, sizeof(header));
|
||||
|
||||
// read the header
|
||||
if ( qlread(li, &header, sizeof(header)) != sizeof(header) )
|
||||
mas_error("unable to read header (%" FMT_Z " bytes)", sizeof(header));
|
||||
|
||||
// granularities that differ from 1 are rare and mostly appear
|
||||
// in DSP CPU's that are not designed for byte processing.
|
||||
if ( header.gran != 1 )
|
||||
mas_error("unsupported granularity (%d)", header.gran);
|
||||
|
||||
// set processor
|
||||
if ( !mas_set_cpu(header.header) )
|
||||
mas_error("processor type '0x%X' is currently unsupported", header.header);
|
||||
if ( !load ) // we have the processor, nothing else to do
|
||||
{
|
||||
finished = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// get segment name
|
||||
const char *segname = mas_get_segname(header.segment);
|
||||
if ( segname == NULL )
|
||||
mas_error("invalid segment '0x%X'", header.segment);
|
||||
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: ready to read %d bytes (0x%X -> 0x%X)\n",
|
||||
header.length, header.start_addr, header.start_addr + header.length);
|
||||
#endif
|
||||
load_bytes(li, header.start_addr, header.length, segname);
|
||||
}
|
||||
break;
|
||||
|
||||
// The last record in a file bears the Header $00 and has only a string as
|
||||
// data field. This string does not have an explicit length specification;
|
||||
// its end is equal to the file's end.
|
||||
//
|
||||
// The string contains only the name of the program that created the file
|
||||
// and has no further meaning.
|
||||
//
|
||||
// creator : x bytes
|
||||
case 0x00:
|
||||
{
|
||||
uint32 length = qlsize(li) - qltell(li);
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: creator length : %ld bytes\n", length);
|
||||
#endif
|
||||
if ( length >= sizeof(creator) )
|
||||
mas_error("creator length is too large (%u >= %" FMT_Z,
|
||||
length, sizeof(creator));
|
||||
ssize_t tmp = qlread(li, creator, length);
|
||||
if ( tmp != length )
|
||||
mas_error("unable to read creator string (i read %" FMT_ZS")", tmp);
|
||||
creator[length] = '\0';
|
||||
}
|
||||
finished = true;
|
||||
break;
|
||||
|
||||
// entry_point : 4 bytes
|
||||
case 0x80:
|
||||
{
|
||||
if ( qlread(li, &entry_point, 4) != 4 )
|
||||
mas_error("unable to read entry_point");
|
||||
if ( load )
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: detected entry point : 0x%X\n", entry_point);
|
||||
#endif
|
||||
inf_set_start_ip(entry_point); // entry point
|
||||
segment_t *s = getseg(entry_point);
|
||||
inf_set_start_cs(s ? s->sel : 0); // selector of code
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// start_addr : 4 bytes
|
||||
// length : 2 bytes
|
||||
// data : length bytes
|
||||
if ( record_type >= 0x01 && record_type <= 0x7F )
|
||||
{
|
||||
check_target_processor();
|
||||
|
||||
struct
|
||||
{
|
||||
int start_addr;
|
||||
short length;
|
||||
} header;
|
||||
|
||||
memset(&header, 0, sizeof(header));
|
||||
|
||||
// read the header
|
||||
if ( qlread(li, &header, sizeof(header)) != sizeof(header) )
|
||||
mas_error("unable to read header (%" FMT_Z " bytes)", sizeof(header));
|
||||
|
||||
if ( load )
|
||||
load_bytes(li, header.start_addr, header.length, "DATA");
|
||||
else
|
||||
qlseek(li, qltell(li)+header.length);
|
||||
}
|
||||
else
|
||||
{
|
||||
mas_error("invalid record type '0x%X'\n", record_type);
|
||||
}
|
||||
}
|
||||
return finished;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// load a macro assembler file in IDA.
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
// already read the 2 first bytes
|
||||
qlseek(li, 2);
|
||||
|
||||
// initialize static variables
|
||||
qstrncpy(creator, "UNKNOWN", sizeof(creator));
|
||||
entry_point = -1;
|
||||
|
||||
bool finished = false;
|
||||
while ( !finished )
|
||||
{
|
||||
uchar record_type = 0;
|
||||
|
||||
// read the record type
|
||||
if ( qlread(li, &record_type, 1) != 1 )
|
||||
mas_error("unable to read the record type");
|
||||
|
||||
finished = process_record(li, record_type, true);
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
msg("MAS: reading complete\n");
|
||||
#endif
|
||||
|
||||
check_target_processor();
|
||||
|
||||
mas_write_comments();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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,
|
||||
};
|
||||
19
idasdk76/ldr/mas/mas.hpp
Normal file
19
idasdk76/ldr/mas/mas.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
#ifndef __MAS_HPP_
|
||||
#define __MAS_HPP_
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#define START_SEQUENCE 0x1489
|
||||
|
||||
struct mas_header_t
|
||||
{
|
||||
uchar header;
|
||||
uchar segment;
|
||||
uchar gran;
|
||||
int start_addr;
|
||||
short length;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* __MAS_HPP_ */
|
||||
|
||||
14
idasdk76/ldr/nlm/makefile
Normal file
14
idasdk76/ldr/nlm/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=nlm
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)nlm$(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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \
|
||||
nlm.cpp nlm.h
|
||||
1023
idasdk76/ldr/nlm/nlm.cpp
Normal file
1023
idasdk76/ldr/nlm/nlm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
43
idasdk76/ldr/nlm/nlm.h
Normal file
43
idasdk76/ldr/nlm/nlm.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef __NLM_H__
|
||||
#define __NLM_H__
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct nlmexe_t
|
||||
{
|
||||
#define NLM_MAGIC_SIZE 0x18
|
||||
char magic[NLM_MAGIC_SIZE];
|
||||
#define NLM_MAGIC "NetWare Loadable Module\x1A"
|
||||
uint32 version; // file Version
|
||||
#define NLM_COMPRESSED 0x00000080L // compressed NLM file
|
||||
char fnamelen; // modulename length
|
||||
char fname[12+1];
|
||||
uint32 codeoff; // offset to code segment
|
||||
uint32 codelen; // length of code segment
|
||||
uint32 dataoff; // offset to data segment
|
||||
uint32 datalen; // length of data segment
|
||||
uint32 bssSize; // Unitialized data size
|
||||
uint32 custoff; // help off
|
||||
uint32 custlen; // help length
|
||||
uint32 autoliboff; // autoload library offset
|
||||
uint32 autolibnum; // number of autoload libraries
|
||||
uint32 fixupoff; // offset to fixups
|
||||
uint32 fixupnum; // number of fixups
|
||||
uint32 impoff; // offset to imported names
|
||||
uint32 impnum; // number of imported names
|
||||
uint32 expoff; // offset to exported names
|
||||
uint32 expnum; // number of exported names
|
||||
uint32 puboff; // offset to public names
|
||||
uint32 pubnum; // number of public names
|
||||
uint32 startIP; // entry point?
|
||||
uint32 endIP; // terminate NLM
|
||||
uint32 auxIP; // additional entry point
|
||||
uint32 modType; // Module type
|
||||
uint32 flags; // Module flags
|
||||
};
|
||||
|
||||
#define NLM_MODNAMOFF 0x82 //sizeof
|
||||
|
||||
CASSERT(NLM_MODNAMOFF == sizeof(nlmexe_t));
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
14
idasdk76/ldr/os9/makefile
Normal file
14
idasdk76/ldr/os9/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=os9
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)os9$(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/mc68xx/notify_codes.hpp \
|
||||
../idaldr.h os9.cpp os9.hpp
|
||||
332
idasdk76/ldr/os9/os9.cpp
Normal file
332
idasdk76/ldr/os9/os9.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov <ig@datarescue.com>
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This file is able to load:
|
||||
* - OS9 object files
|
||||
* - FLEX STX files
|
||||
* for 6809
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "../../module/mc68xx/notify_codes.hpp"
|
||||
#include "os9.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void swap_os9_header(os9_header_t &h)
|
||||
{
|
||||
#if __MF__
|
||||
qnotused(h);
|
||||
#else
|
||||
h.magic = swap16(h.magic);
|
||||
h.size = swap16(h.size);
|
||||
h.name = swap16(h.name);
|
||||
h.start = swap16(h.start);
|
||||
h.storage = swap16(h.storage);
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// calc header parity
|
||||
static uchar calc_os9_parity(os9_header_t &h)
|
||||
{
|
||||
uchar *ptr = (uchar *)&h;
|
||||
int parity = 0;
|
||||
for ( int i=0; i < 8; i++ )
|
||||
parity ^= *ptr++;
|
||||
return (uchar)~parity;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char object_name[] = "OS9 object file for 6809";
|
||||
static bool is_os9_object_file(qstring *fileformatname, linput_t *li)
|
||||
{
|
||||
os9_header_t h;
|
||||
qlseek(li, 0);
|
||||
if ( qlread(li,&h,sizeof(os9_header_t)) != sizeof(os9_header_t) )
|
||||
return false;
|
||||
swap_os9_header(h);
|
||||
if ( h.magic == OS9_MAGIC
|
||||
&& calc_os9_parity(h) == h.parity
|
||||
&& (h.type_lang & OS9_LANG) == OS9_LANG_OBJ )
|
||||
{
|
||||
*fileformatname = object_name;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char flex_name[] = "FLEX STX file";
|
||||
static bool is_os9_flex_file(qstring *fileformatname, linput_t *li)
|
||||
{
|
||||
qlseek(li, 0);
|
||||
int64 fsize = qlsize(li);
|
||||
int nrec2 = 0;
|
||||
qoff64_t fpos = 0;
|
||||
while ( 1 )
|
||||
{
|
||||
if ( fpos > fsize )
|
||||
return false;
|
||||
qlseek(li, fpos, SEEK_SET);
|
||||
int c = qlgetc(li);
|
||||
if ( c == EOF )
|
||||
break;
|
||||
if ( fpos == 0 && c != 0x2 )
|
||||
return false; // the first byte must be 0x2
|
||||
switch ( c )
|
||||
{
|
||||
case 0:
|
||||
fpos++;
|
||||
break;
|
||||
case 0x2:
|
||||
{
|
||||
c = qlgetc(li);
|
||||
int adr = (c<<8) | qlgetc(li);
|
||||
if ( adr == EOF )
|
||||
return false;
|
||||
c = qlgetc(li); // number of bytes
|
||||
if ( c == 0 || c == EOF )
|
||||
return false;
|
||||
fpos += c+4;
|
||||
nrec2++;
|
||||
}
|
||||
break;
|
||||
case 0x16:
|
||||
fpos += 3;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( nrec2 == 0 )
|
||||
return false;
|
||||
*fileformatname = flex_name;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
if ( is_os9_object_file(fileformatname, li) // OS9
|
||||
|| is_os9_flex_file(fileformatname, li) ) // FLEX
|
||||
{
|
||||
*processor = "6809";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char *get_os9_type_name(uchar type)
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case OS9_TYPE_ILL: return "illegal";
|
||||
case OS9_TYPE_PRG: return "Program module";
|
||||
case OS9_TYPE_SUB: return "Subroutine module";
|
||||
case OS9_TYPE_MUL: return "Multi-Module (for future use)";
|
||||
case OS9_TYPE_DAT: return "Data module";
|
||||
case OS9_TYPE_SYS: return "OS-9 System Module";
|
||||
case OS9_TYPE_FIL: return "OS-9 File Manager Module";
|
||||
case OS9_TYPE_DRV: return "OS-9 Device Driver Module";
|
||||
case OS9_TYPE_DDM: return "OS-9 Device Descriptor Module";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char *get_os9_lang_name(uchar lang)
|
||||
{
|
||||
switch ( lang )
|
||||
{
|
||||
case OS9_LANG_DAT: return "Data (not executable)";
|
||||
case OS9_LANG_OBJ: return "6809 object code";
|
||||
case OS9_LANG_BAS: return "BASIC09 I-Code";
|
||||
case OS9_LANG_PAS: return "PASCAL P-Code";
|
||||
case OS9_LANG_C: return "C I-Code";
|
||||
case OS9_LANG_CBL: return "COBOL I-Code";
|
||||
case OS9_LANG_FTN: return "FORTRAN I-Code";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void create32(
|
||||
sel_t sel,
|
||||
ea_t start_ea,
|
||||
ea_t end_ea,
|
||||
const char *name,
|
||||
const char *classname)
|
||||
{
|
||||
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 = scPub;
|
||||
if ( !add_segm_ex(&s, name, classname, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
#define LOADING_OFFSET 0x1000
|
||||
|
||||
void load_obj_file(linput_t *li)
|
||||
{
|
||||
os9_header_t h;
|
||||
qlseek(li, 0);
|
||||
lread(li, &h, sizeof(os9_header_t));
|
||||
swap_os9_header(h);
|
||||
|
||||
set_processor_type("6809", SETPROC_LOADER);
|
||||
set_target_assembler(5);
|
||||
|
||||
uint64 fsize = qlsize(li);
|
||||
qoff64_t fpos = qltell(li);
|
||||
uint64 rest = fsize - fpos;
|
||||
ea_t start = to_ea(inf_get_baseaddr(), LOADING_OFFSET);
|
||||
ea_t end = start + h.size;
|
||||
if ( end <= start || fsize < fpos || fsize-fpos < rest )
|
||||
loader_failure("Corrupted input file");
|
||||
|
||||
file2base(li, 0, start, end, FILEREG_PATCHABLE);
|
||||
create32(inf_get_baseaddr(), start, start + h.size, "TEXT", "CODE");
|
||||
|
||||
create_filename_cmt();
|
||||
ea_t ea = start;
|
||||
set_name(ea, "magic", SN_IDBENC);
|
||||
create_word(ea, 2);
|
||||
op_num(ea,0);
|
||||
|
||||
ea += 2;
|
||||
set_name(ea, "size", SN_IDBENC);
|
||||
create_word(ea, 2);
|
||||
op_num(ea,0);
|
||||
|
||||
ea += 2;
|
||||
set_name(ea, "name", SN_IDBENC);
|
||||
create_word(ea, 2);
|
||||
if ( h.name < h.size )
|
||||
op_plain_offset(ea,0, start);
|
||||
|
||||
ea += 2;
|
||||
set_name(ea, "type_lang", SN_IDBENC);
|
||||
create_byte(ea, 1);
|
||||
op_num(ea,0);
|
||||
append_cmt(ea, get_os9_type_name(h.type_lang & OS9_TYPE), 0);
|
||||
append_cmt(ea, get_os9_lang_name(h.type_lang & OS9_LANG), 0);
|
||||
|
||||
ea += 1;
|
||||
set_name(ea, "attrib", SN_IDBENC);
|
||||
create_byte(ea, 1);
|
||||
op_num(ea,0);
|
||||
if ( h.attrib & OS9_SHARED )
|
||||
append_cmt(ea, "Shared module", 0);
|
||||
|
||||
ea += 1;
|
||||
set_name(ea, "parity", SN_IDBENC);
|
||||
create_byte(ea, 1);
|
||||
op_num(ea,0);
|
||||
|
||||
ea += 1;
|
||||
set_name(ea, "start_ptr", SN_IDBENC);
|
||||
create_word(ea, 2);
|
||||
op_plain_offset(ea,0, start);
|
||||
|
||||
ea += 2;
|
||||
set_name(ea, "storage", SN_IDBENC);
|
||||
create_word(ea, 2); op_num(ea,0);
|
||||
|
||||
inf_set_start_ip(LOADING_OFFSET + h.start);
|
||||
inf_set_start_cs(inf_get_baseaddr());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void load_flex_file(linput_t *li)
|
||||
{
|
||||
qlseek(li, 0);
|
||||
|
||||
set_processor_type("6809", SETPROC_LOADER);
|
||||
set_target_assembler(5);
|
||||
|
||||
ea_t bottom = BADADDR;
|
||||
ea_t top = 0;
|
||||
while ( 1 )
|
||||
{
|
||||
int c = qlgetc(li);
|
||||
if ( c == EOF )
|
||||
break;
|
||||
switch ( c )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 0x2:
|
||||
{
|
||||
c = qlgetc(li);
|
||||
int adr = (c<<8) | qlgetc(li);
|
||||
c = qlgetc(li); // number of bytes
|
||||
ea_t start = to_ea(inf_get_baseaddr(), adr);
|
||||
ea_t end = start + c;
|
||||
file2base(li, qltell(li), start, end, FILEREG_PATCHABLE);
|
||||
if ( bottom > start )
|
||||
bottom = start;
|
||||
if ( top < end )
|
||||
top = end;
|
||||
}
|
||||
break;
|
||||
case 0x16:
|
||||
c = qlgetc(li);
|
||||
inf_set_start_ip(int(c<<8) | qlgetc(li));
|
||||
inf_set_start_cs(inf_get_baseaddr());
|
||||
break;
|
||||
default:
|
||||
INTERR(20065);
|
||||
}
|
||||
}
|
||||
create32(inf_get_baseaddr(), bottom, top, "TEXT", "CODE");
|
||||
create_filename_cmt();
|
||||
mc68xx_module_t::notify_flex_format(); // tell the module that the file has FLEX format
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li,ushort /*_neflags*/,const char *fileformatname)
|
||||
{
|
||||
if ( strcmp(fileformatname, object_name) == 0 )
|
||||
load_obj_file(li);
|
||||
else
|
||||
load_flex_file(li);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
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,
|
||||
};
|
||||
78
idasdk76/ldr/os9/os9.hpp
Normal file
78
idasdk76/ldr/os9/os9.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov <ig@datarescue.com>
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* This file describes two different formats:
|
||||
* - OS9 object files
|
||||
* - FLEX STX files
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _OS9_HPP
|
||||
#define _OS9_HPP
|
||||
#pragma pack(push, 1)
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// OS9 object code files have the following header at the start:
|
||||
//
|
||||
struct os9_header_t
|
||||
{
|
||||
ushort magic; // $00 2 Sync Bytes (always $87CD)
|
||||
#define OS9_MAGIC 0x87CD
|
||||
ushort size; // $02 2 Module Size (bytes)
|
||||
ushort name; // $04 2 Module Name Offset
|
||||
uchar type_lang; // $06 1 Type/Language
|
||||
#define OS9_TYPE 0xF0 // Type
|
||||
#define OS9_TYPE_ILL 0x00 // this one is illegal
|
||||
#define OS9_TYPE_PRG 0x10 // Program module
|
||||
#define OS9_TYPE_SUB 0x20 // Subroutine module
|
||||
#define OS9_TYPE_MUL 0x30 // Multi-Module (for future use)
|
||||
#define OS9_TYPE_DAT 0x40 // Data module
|
||||
//#define OS9_$50-$B0 User defined
|
||||
#define OS9_TYPE_SYS 0xC0 // OS-9 System Module
|
||||
#define OS9_TYPE_FIL 0xD0 // OS-9 File Manager Module
|
||||
#define OS9_TYPE_DRV 0xE0 // OS-9 Device Driver Module
|
||||
#define OS9_TYPE_DDM 0xF0 // OS-9 Device Descriptor Module
|
||||
|
||||
#define OS9_LANG 0x0F // Language
|
||||
#define OS9_LANG_DAT 0x00 // Data (not executable)
|
||||
#define OS9_LANG_OBJ 0x01 // 6809 object code <- this is the only one to disassemble
|
||||
#define OS9_LANG_BAS 0x02 // BASIC09 I-Code
|
||||
#define OS9_LANG_PAS 0x03 // PASCAL P-Code
|
||||
#define OS9_LANG_C 0x04 // C I-Code
|
||||
#define OS9_LANG_CBL 0x05 // COBOL I-Code
|
||||
#define OS9_LANG_FTN 0x06 // FORTRAN I-Code
|
||||
uchar attrib; // $07 1 Attrib/Revision
|
||||
#define OS9_REVSN 0x0F // Module revision
|
||||
// The higher the number the more current
|
||||
// the revision. When modules are loaded by
|
||||
// the OS, if there is already module loaded
|
||||
// with the same name, type, language, etc.
|
||||
// the one with the highest revision will be used.
|
||||
#define OS9_SHARED 0x80 // The module is reentrant and sharable
|
||||
uchar parity; // $08 1 header parity byte
|
||||
// It is the ones complement of the vertical
|
||||
// parity (exclusive OR) of the previous
|
||||
// eight bytes.
|
||||
ushort start; // $09 2 Execution Offset
|
||||
ushort storage; // $0B 2 Permenant Storage Requirements
|
||||
// $0D Module Body
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Flex files have the following format:
|
||||
// 0x02 0xYY 0xYY 0xZZ ...........
|
||||
// where 0xYY is a 16 bit address, and 0xZZ is the byte count (0x00-0xFF).
|
||||
// The reason for this is that the user could assign a program to be
|
||||
// loaded and executed from anywhere in memory. So each executable file
|
||||
// had the loading info in the file.
|
||||
// 0x16 0xYY 0xYY
|
||||
// The starting address of the program was specified in the binary files
|
||||
// with a 0x16 0xYY 0xYY record. The 0xYY was the transfer address to be
|
||||
// JMP'ed to when the program finished loading. This is the way FLEX and
|
||||
// SK*DOS worked for the 6800, 6809 and 68K.
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // define _OS9_HPP
|
||||
701
idasdk76/ldr/pe/common.cpp
Normal file
701
idasdk76/ldr/pe/common.cpp
Normal file
@@ -0,0 +1,701 @@
|
||||
|
||||
#include <auto.hpp>
|
||||
#include "common.h"
|
||||
#include "../idaldr.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
#ifdef LOADER_SOURCE // building a loader?
|
||||
AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
qstring question("AUTOHIDE REGISTRY\n");
|
||||
question.cat_vsprnt(format, va);
|
||||
question.append("\nDo you wish to continue?");
|
||||
if ( ask_yn(ASKBTN_YES, "%s", question.c_str()) != ASKBTN_YES )
|
||||
{
|
||||
loader_failure(NULL);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
#else
|
||||
// for other purposes: just print the error message and continue
|
||||
AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
qvprintf(format, va);
|
||||
qprintf("\n");
|
||||
va_end(va);
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe64_to_pe(peheader_t &pe, const peheader64_t &pe64, bool silent, bool zero_bad_data)
|
||||
{
|
||||
bool ok = true;
|
||||
switch ( pe64.magic )
|
||||
{
|
||||
default:
|
||||
if ( !silent )
|
||||
{
|
||||
ask_for_feedback("The input file has non-standard magic number (%x)",
|
||||
pe64.magic);
|
||||
}
|
||||
ok = false;
|
||||
/* no break */
|
||||
case MAGIC_P32:
|
||||
case MAGIC_ROM:
|
||||
case 0:
|
||||
memcpy(&pe, &pe64, sizeof(pe));
|
||||
break;
|
||||
case MAGIC_P32_PLUS:
|
||||
// Copy the constant part
|
||||
memcpy(&pe, &pe64, offsetof(peheader_t, stackres));
|
||||
|
||||
// Copy after the changed part
|
||||
memcpy(&pe.loaderflags, &pe64.loaderflags,
|
||||
sizeof(pe) - qoffsetof(peheader_t, loaderflags));
|
||||
|
||||
// Truncate the 64bit to 32bit
|
||||
pe.stackres = low(pe64.stackres);
|
||||
pe.stackcom = low(pe64.stackcom);
|
||||
pe.heapres = low(pe64.heapres);
|
||||
pe.heapcom = low(pe64.heapcom);
|
||||
break;
|
||||
}
|
||||
// Do various checks
|
||||
if ( !pe.is_efi()
|
||||
&& (pe.objalign < pe.filealign
|
||||
|| pe.filealign != 0 && (pe.filealign & (pe.filealign-1)) != 0 // check for power of 2
|
||||
|| pe.objalign != 0 && (pe.objalign & (pe.objalign -1)) != 0) ) // check for power of 2
|
||||
{
|
||||
if ( !silent )
|
||||
pe_failure("Invalid file: bad alignment value specified (section alignment: %08X, file alignment: %08X)", pe.objalign, pe.filealign);
|
||||
}
|
||||
if ( pe.imagesize > 0x77000000 || pe.imagesize < pe.allhdrsize )
|
||||
{
|
||||
if ( !silent )
|
||||
pe_failure("Invalid file: bad ImageSize value %x", pe.imagesize);
|
||||
}
|
||||
|
||||
if ( zero_bad_data )
|
||||
{
|
||||
if ( pe.nrvas != 0 && pe.nrvas < total_rvatab_count )
|
||||
memset(&pe.expdir + pe.nrvas, 0, total_rvatab_size - pe.nrvas * sizeof(petab_t));
|
||||
size_t fullhdrsize = pe.is_pe_plus() ? sizeof(pe64) : sizeof(pe);
|
||||
size_t sectblstart = pe.first_section_pos(0);
|
||||
// clear items covered by section table
|
||||
if ( sectblstart < fullhdrsize
|
||||
&& total_rvatab_size < fullhdrsize
|
||||
&& sectblstart >= fullhdrsize - total_rvatab_size )
|
||||
{
|
||||
if ( !silent )
|
||||
msg("Warning: image directories are covered by the section table, some entries will be ignored\n");
|
||||
size_t clearcount = (fullhdrsize - sectblstart + sizeof(petab_t) -1 )/ sizeof(petab_t);
|
||||
memset(&pe.expdir + (total_rvatab_count- clearcount), 0, clearcount * sizeof(petab_t));
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool te_to_pe(peheader_t &pe, const teheader_t &te)
|
||||
{
|
||||
bool ok = true;
|
||||
memset(&pe, 0, sizeof(pe));
|
||||
pe.signature = te.signature;
|
||||
pe.machine = te.machine;
|
||||
pe.nobjs = te.nobjs;
|
||||
pe.magic = pe.is_64bit_cpu() ? MAGIC_P32_PLUS : MAGIC_P32;
|
||||
pe.entry = te.entry;
|
||||
pe.text_start = te.text_start;
|
||||
pe.allhdrsize = te.text_start + te.te_adjust();
|
||||
if ( pe.is_pe_plus() )
|
||||
pe.imagebase64 = te.imagebase64;
|
||||
else
|
||||
pe.imagebase32 = te.imagebase64;
|
||||
pe.subsys = te.subsys;
|
||||
pe.reltab = te.reltab;
|
||||
pe.debdir = te.debdir;
|
||||
pe.objalign = 1;
|
||||
pe.filealign = 1;
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data)
|
||||
{
|
||||
peoff = _peoff;
|
||||
qlseek(li, peoff);
|
||||
memset(&pe64, 0, sizeof(pe64));
|
||||
qlseek(li, peoff);
|
||||
size_t size = qlread(li, &pe64, sizeof(pe64));
|
||||
size_t minsize = pe64.magic == MAGIC_P32_PLUS
|
||||
? qoffsetof(peheader64_t, subsys)
|
||||
: qoffsetof(peheader_t, subsys);
|
||||
bool ok = size > minsize
|
||||
&& size <= sizeof(pe64)
|
||||
&& (pe64.signature == PEEXE_ID || pe64.signature == BPEEXE_ID || pe64.signature == PLEXE_ID)
|
||||
&& pe64_to_pe(pe, pe64, silent, zero_bad_data);
|
||||
if ( ok )
|
||||
{
|
||||
// initialize imagebase for loading
|
||||
set_imagebase((ea_t)pe.imagebase());
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::read_header(linput_t *li, bool silent, bool zero_bad_data)
|
||||
{
|
||||
uint32 hdroff = 0;
|
||||
link_ulink = false;
|
||||
|
||||
qlseek(li, hdroff);
|
||||
if ( qlread(li, &exe, sizeof(exe)) != sizeof(exe) )
|
||||
return false;
|
||||
if ( exe.exe_ident != PEEXE_ID )
|
||||
{
|
||||
if ( exe.exe_ident == TEEXE_ID )
|
||||
{
|
||||
qlseek(li, hdroff);
|
||||
if ( qlread(li, &te, sizeof(te)) != sizeof(te) )
|
||||
return false;
|
||||
bool ok = te_to_pe(pe, te);
|
||||
if ( ok )
|
||||
{
|
||||
// initialize imagebase for loading
|
||||
set_imagebase((ea_t)pe.imagebase());
|
||||
peoff = hdroff;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
if ( exe.exe_ident == EXE_ID || exe.exe_ident == EXE_ID2 )
|
||||
{
|
||||
char tmp[8];
|
||||
if ( qlread(li, tmp, sizeof(tmp)) == sizeof(tmp)
|
||||
&& memcmp(tmp, "UniLink", 8) == 0 )
|
||||
{
|
||||
link_ulink = true;
|
||||
}
|
||||
qlseek(li, PE_PTROFF);
|
||||
if ( qlread(li, &hdroff, sizeof(hdroff)) != sizeof(hdroff) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return read_header(li, hdroff, silent, zero_bad_data);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::vseek(linput_t *li, uint32 rva)
|
||||
{
|
||||
ea_t fpos = get_linput_type(li) == LINPUT_PROCMEM ? rva : map_ea(rva);
|
||||
if ( fpos != BADADDR )
|
||||
{
|
||||
qlseek(li, fpos);
|
||||
return true;
|
||||
}
|
||||
qlseek(li, rva, SEEK_SET);
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline char *pe_loader_t::asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok)
|
||||
{
|
||||
vseek(li, rva);
|
||||
buf[0] = '\0';
|
||||
char *ret = qlgetz(li, -1, buf, bufsize);
|
||||
*ok = buf[0] != '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// same as asciiz() but don't set ok to false for successfully read empty strings
|
||||
inline char *pe_loader_t::asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok)
|
||||
{
|
||||
vseek(li, rva);
|
||||
buf[0] = '\0';
|
||||
// do not use qlgetz() here because we won't distinguish empty strings from read errors
|
||||
ssize_t readsize = qlread(li, buf, bufsize-1);
|
||||
if ( readsize < 0 || readsize >= bufsize )
|
||||
*ok = false;
|
||||
else
|
||||
buf[readsize] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_sections(
|
||||
linput_t *li,
|
||||
off_t first_sec_pos,
|
||||
int nobjs,
|
||||
pe_section_visitor_t &psv)
|
||||
{
|
||||
transvec.qclear();
|
||||
qvector<pesection_t> sec_headers;
|
||||
// does the file layout match memory layout?
|
||||
bool alt_align = pe.objalign == pe.filealign && pe.objalign < PAGE_SIZE;
|
||||
qlseek(li, first_sec_pos);
|
||||
validate_array_count(li, &nobjs, sizeof(pesection_t), "Number of sections", first_sec_pos);
|
||||
for ( int i=0; i < nobjs; i++ )
|
||||
{
|
||||
pesection_t &sh = sec_headers.push_back();
|
||||
if ( qlread(li, &sh, sizeof(sh)) != sizeof(sh) )
|
||||
return -1;
|
||||
if ( sh.s_vaddr != uint32(sh.s_scnptr) || sh.s_vsize > sh.s_psize )
|
||||
alt_align = false;
|
||||
}
|
||||
if ( alt_align || pe.is_te() )
|
||||
{
|
||||
// according to Ivan Teblin from AVERT Labs, such files are
|
||||
// mapped by Windows as-is and not section by section
|
||||
// we mimic that behaviour
|
||||
int code = psv.load_all();
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
}
|
||||
|
||||
int off_align = alt_align ? pe.filealign : FILEALIGN;
|
||||
if ( pe.is_efi() || pe.is_te() )
|
||||
off_align = 1;
|
||||
|
||||
uint32 max_va = 0;
|
||||
for ( int i=0; i < nobjs; i++ )
|
||||
{
|
||||
pesection_t &sh = sec_headers[i];
|
||||
uint32 scnptr = align_down(sh.s_scnptr, off_align);
|
||||
transl_t &tr = transvec.push_back();
|
||||
tr.start = sh.s_vaddr;
|
||||
tr.psize = sh.get_psize(pe);
|
||||
tr.end = pe.align_up_in_file(uint32(sh.s_vaddr + tr.psize));
|
||||
tr.pos = scnptr;
|
||||
if ( pe.is_te() )
|
||||
tr.pos += te.te_adjust();
|
||||
int code = psv.visit_section(sh, scnptr);
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
if ( max_va < sh.s_vaddr + sh.s_vsize )
|
||||
max_va = sh.s_vaddr + sh.s_vsize;
|
||||
}
|
||||
if ( pe.is_te() )
|
||||
pe.imagesize = max_va;
|
||||
if ( nobjs == 0 || alt_align )
|
||||
{
|
||||
// add mapping for the header
|
||||
transl_t tr;
|
||||
tr.start = 0;
|
||||
tr.psize = qlsize(li);
|
||||
tr.end = pe.align_up_in_file(pe.imagesize);
|
||||
tr.pos = 0;
|
||||
// insert at the front so that it's always consulted last
|
||||
transvec.insert(transvec.begin(), tr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_sections(linput_t *li, pe_section_visitor_t &psv)
|
||||
{
|
||||
off_t first_sec_pos = pe.is_te() ? te.first_section_pos(peoff) : pe.first_section_pos(peoff);
|
||||
return process_sections(li, first_sec_pos, pe.nobjs, psv);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_sections(linput_t *li)
|
||||
{
|
||||
pe_section_visitor_t v;
|
||||
return process_sections(li, v);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline void to_utf8(char *buf, size_t bufsz, bool force=false)
|
||||
{
|
||||
if ( force || !is_valid_utf8(buf) )
|
||||
{
|
||||
qstring qbuf;
|
||||
if ( idb_utf8(&qbuf, buf) )
|
||||
qstrncpy(buf, qbuf.c_str(), bufsz);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// process import table for one dll
|
||||
inline int pe_loader_t::process_import_table(
|
||||
linput_t *li,
|
||||
ea_t atable,
|
||||
ea_t ltable,
|
||||
pe_import_visitor_t &piv)
|
||||
{
|
||||
bool is_pe_plus = pe.is_pe_plus();
|
||||
uint32 elsize = piv.elsize = is_pe_plus ? 8 : 4;
|
||||
const uint64 mask = is_pe_plus ? IMP_BY_ORD64 : IMP_BY_ORD32;
|
||||
bool ok = true;
|
||||
uint32 i;
|
||||
for ( i=0; ok; i++, atable += elsize )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
if ( !is_mul_ok(i, elsize) )
|
||||
return 1;
|
||||
uval_t rva_off = i * elsize;
|
||||
if ( !is_add_ok(ltable, rva_off) )
|
||||
return 1;
|
||||
ea_t rva = ltable + rva_off;
|
||||
if ( piv.withbase )
|
||||
rva -= (uval_t)pe.imagebase();
|
||||
uint32 fof = uint32(rva);
|
||||
uint64 entry = is_pe_plus ? vaint64(li, fof, &ok) : valong(li, fof, &ok);
|
||||
if ( entry == 0 )
|
||||
break;
|
||||
show_addr(atable);
|
||||
|
||||
int code;
|
||||
if ( (entry & mask) == 0 ) // by name
|
||||
{
|
||||
ea_t nrva = (uval_t)entry + sizeof(short);
|
||||
if ( piv.withbase )
|
||||
nrva -= (uval_t)pe.imagebase();
|
||||
fof = uint32(nrva);
|
||||
asciiz2(li, fof, buf, sizeof(buf), &ok);
|
||||
to_utf8(buf, sizeof(buf));
|
||||
code = piv.visit_import(atable, entry, buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ordinals are always 32bit, even in pe64
|
||||
uint32 ord = entry & ~mask;
|
||||
code = piv.visit_import(atable, ord, NULL);
|
||||
}
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
}
|
||||
return piv.leave_module(i);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// this function tries to read from a file as if it was reading from memory
|
||||
// if translation not found for the given RVA then ZEROs are returned
|
||||
// in addition, if it tries to read beyond a translation physical size
|
||||
// the additional bytes will be returned as zeros
|
||||
inline bool pe_loader_t::vmread(linput_t *li, uint32 rva, void *buf, size_t sz)
|
||||
{
|
||||
// clear whole user buffer
|
||||
memset(buf, 0, sz);
|
||||
|
||||
size_t may_read = sz;
|
||||
if ( get_linput_type(li) == LINPUT_PROCMEM )
|
||||
{
|
||||
qlseek(li, rva, SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
const transl_t *tr;
|
||||
ea_t fpos = map_ea(rva, &tr);
|
||||
|
||||
// cannot find translation?
|
||||
if ( fpos == BADADDR )
|
||||
{
|
||||
qlseek(li, int32(rva), SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
uint32 sectend = tr->pos + tr->psize; // section end
|
||||
if ( fpos >= sectend )
|
||||
return false; // data not present in the input file
|
||||
qlseek(li, fpos);
|
||||
|
||||
// reading beyond section's limit?
|
||||
uint32 after_read_pos = fpos + sz;
|
||||
if ( after_read_pos < fpos )
|
||||
return false; // integer overflow
|
||||
if ( after_read_pos >= sectend )
|
||||
{
|
||||
// check if position belongs to the header and if reading beyond the limit
|
||||
if ( uint32(fpos) < pe.allhdrsize && after_read_pos > pe.allhdrsize )
|
||||
may_read = pe.allhdrsize - size_t(fpos);
|
||||
else
|
||||
may_read = sectend - fpos; // just read as much as section limit allows
|
||||
}
|
||||
}
|
||||
QASSERT(20045, ssize_t(may_read) >= 0);
|
||||
return qlread(li, buf, may_read) == (ssize_t)may_read;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// process all imports of a pe file
|
||||
// returns: -1:could not read an impdir; 0-ok;
|
||||
// other values can be returned by the visitor
|
||||
inline int pe_loader_t::process_imports(linput_t *li, pe_import_visitor_t &piv)
|
||||
{
|
||||
if ( pe.impdir.rva == 0 )
|
||||
return 0;
|
||||
|
||||
if ( transvec.empty() )
|
||||
process_sections(li);
|
||||
|
||||
int code = 0;
|
||||
for ( int ni=0; ; ni++ )
|
||||
{
|
||||
off_t off = pe.impdir.rva + ni*sizeof(peimpdir_t);
|
||||
peimpdir_t &id = piv.id;
|
||||
|
||||
if ( !vmread(li, off, &id, sizeof(id)) )
|
||||
{
|
||||
memset(&id, 0, sizeof(id));
|
||||
// we continue if the import descriptor is within the page belonging
|
||||
// to the program
|
||||
if ( map_ea(off) == BADADDR || map_ea(off+sizeof(id)-1) == BADADDR )
|
||||
{
|
||||
code = piv.impdesc_error(off);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( id.dllname == 0 || id.looktab == 0 )
|
||||
break;
|
||||
ea_t ltable = id.table1; // OriginalFirstThunk
|
||||
ea_t atable = id.looktab; // FirstThunk
|
||||
bool ok = true;
|
||||
char dll[MAXSTR];
|
||||
asciiz(li, id.dllname, dll, sizeof(dll), &ok);
|
||||
if ( !ok )
|
||||
break;
|
||||
to_utf8(dll, sizeof(dll), /*force=*/ true);
|
||||
if ( map_ea(ltable) == BADADDR
|
||||
|| ltable < pe.allhdrsize
|
||||
|| pe.imagesize != 0 && ltable >= pe.imagesize )
|
||||
{
|
||||
ltable = atable;
|
||||
}
|
||||
atable += get_imagebase();
|
||||
code = piv.visit_module(dll, atable, ltable);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
code = process_import_table(li, atable, ltable, piv);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline int pe_loader_t::process_delayed_imports(linput_t *li, pe_import_visitor_t &il)
|
||||
{
|
||||
if ( pe.didtab.rva == 0 )
|
||||
return 0;
|
||||
|
||||
if ( transvec.empty() )
|
||||
process_sections(li);
|
||||
|
||||
int code = 0;
|
||||
uint32 ni = 0;
|
||||
bool ok = true;
|
||||
while ( true )
|
||||
{
|
||||
uint32 table = pe.didtab.rva + ni*uint32(sizeof(dimpdir_t));
|
||||
if ( !vseek(li, table) )
|
||||
break;
|
||||
dimpdir_t &id = il.did;
|
||||
if ( qlread(li, &id, sizeof(id)) != sizeof(id) )
|
||||
return -1;
|
||||
if ( !id.dllname )
|
||||
break;
|
||||
il.withbase = (id.attrs & DIMP_NOBASE) == 0;
|
||||
uval_t base = il.withbase ? 0 : uval_t(get_imagebase());
|
||||
ea_t atable = id.diat + base;
|
||||
ea_t ltable = id.dint;
|
||||
char dll[MAXSTR];
|
||||
uint32 off = uint32(il.withbase ? id.dllname - (ea_t)pe.imagebase() : id.dllname);
|
||||
asciiz(li, off, dll, sizeof(dll), &ok);
|
||||
if ( !ok )
|
||||
break;
|
||||
to_utf8(dll, sizeof(dll), /*force=*/ true);
|
||||
code = il.visit_module(dll, atable, ltable);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
code = process_import_table(li, atable, ltable, il);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
ni++;
|
||||
}
|
||||
return ok || code != 0 ? code : -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// process all exports of a pe file
|
||||
// returns -2: could not read expdir, -1: other read errors, 0-ok,
|
||||
// other values can be returned by the visitor
|
||||
inline int pe_loader_t::process_exports(linput_t *li, pe_export_visitor_t &pev)
|
||||
{
|
||||
if ( pe.expdir.rva == 0 )
|
||||
return 0;
|
||||
if ( transvec.empty() )
|
||||
process_sections(li);
|
||||
if ( !vseek(li, pe.expdir.rva) )
|
||||
return -2;
|
||||
|
||||
// process export directory
|
||||
bool fok = true;
|
||||
char buf[MAXSTR];
|
||||
peexpdir_t ed;
|
||||
if ( qlread(li, &ed, sizeof(ed)) != sizeof(ed) )
|
||||
return -1;
|
||||
asciiz2(li, ed.dllname, buf, sizeof(buf), &fok);
|
||||
to_utf8(buf, sizeof(buf), /*force=*/ true);
|
||||
int code = pev.visit_expdir(ed, buf);
|
||||
if ( code != 0 )
|
||||
return code;
|
||||
|
||||
// I'd like to have a better validation
|
||||
uint64 maxsize = qlsize(li) + 4096;
|
||||
if ( maxsize > pe.expdir.size && pe.expdir.size != 0 )
|
||||
maxsize = pe.expdir.size;
|
||||
validate_array_count(NULL, &ed.nnames, 6, "Number of exported names",
|
||||
pe.expdir.rva, pe.expdir.rva+maxsize);
|
||||
validate_array_count(NULL, &ed.naddrs, 4, "Number of exported addresses",
|
||||
pe.expdir.rva, pe.expdir.rva+maxsize);
|
||||
|
||||
// gather name information
|
||||
typedef std::map<int, qstring> names_t;
|
||||
names_t names;
|
||||
int rcode = fok ? 0 : -1;
|
||||
for ( uint32 i=0; i < ed.nnames; i++ )
|
||||
{
|
||||
fok = true;
|
||||
uint32 ordidx = vashort(li, ed.ordtab + i*sizeof(ushort), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
ushort ord = ushort(ordidx + ed.ordbase);
|
||||
uint32 rva = valong(li, ed.namtab + i*sizeof(uint32), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
asciiz2(li, rva, buf, sizeof(buf), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
to_utf8(buf, sizeof(buf));
|
||||
names[ord] = buf;
|
||||
}
|
||||
|
||||
// visit all exports
|
||||
uint32 expdir_start_rva = pe.expdir.rva;
|
||||
uint32 expdir_end_rva = pe.expdir.rva + maxsize;
|
||||
|
||||
for ( uint32 i = 0; i < ed.naddrs; i++ )
|
||||
{
|
||||
fok = true;
|
||||
uint32 rva = valong(li, ed.adrtab + i*sizeof(uint32), &fok);
|
||||
if ( rva != 0 && fok )
|
||||
{
|
||||
uint32 ord = i + ed.ordbase;
|
||||
names_t::iterator p = names.find(ord);
|
||||
const char *name = p != names.end() ? p->second.c_str() : "";
|
||||
const char *forwarder = NULL;
|
||||
if ( rva >= expdir_start_rva && rva < expdir_end_rva )
|
||||
{
|
||||
// string inside export directory: this is a forwarded export
|
||||
asciiz(li, rva, buf, sizeof(buf), &fok);
|
||||
if ( !fok )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = -1;
|
||||
continue;
|
||||
}
|
||||
char *dot = strrchr(buf, '.');
|
||||
if ( dot != NULL )
|
||||
{
|
||||
char before_dot[MAXSTR];
|
||||
char after_dot[MAXSTR];
|
||||
*dot = '\0';
|
||||
qstrncpy(before_dot, buf, sizeof(before_dot));
|
||||
qstrncpy(after_dot, dot+1, sizeof(after_dot));
|
||||
to_utf8(before_dot, sizeof(before_dot), /*force=*/ true);
|
||||
to_utf8(after_dot, sizeof(after_dot), /*force=*/ false);
|
||||
qsnprintf(buf, sizeof(buf), "%s.%s", before_dot, after_dot);
|
||||
}
|
||||
else
|
||||
{
|
||||
to_utf8(buf, sizeof(buf), /*force=*/ true);
|
||||
}
|
||||
forwarder = buf;
|
||||
}
|
||||
code = pev.visit_export(rva, ord, name, forwarder);
|
||||
if ( code != 0 )
|
||||
{
|
||||
if ( rcode == 0 )
|
||||
rcode = code;
|
||||
}
|
||||
}
|
||||
else if ( !fok )
|
||||
rcode = -1;
|
||||
}
|
||||
|
||||
return rcode;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline const char *get_pe_machine_name(uint16 machine)
|
||||
{
|
||||
switch ( machine )
|
||||
{
|
||||
case PECPU_80386: return "80386";
|
||||
case PECPU_80486: return "80486";
|
||||
case PECPU_80586: return "80586";
|
||||
case PECPU_SH3: return "SH3";
|
||||
case PECPU_SH3DSP: return "SH3DSP";
|
||||
case PECPU_SH3E: return "SH3E";
|
||||
case PECPU_SH4: return "SH4";
|
||||
case PECPU_SH5: return "SH5";
|
||||
case PECPU_ARM: return "ARM";
|
||||
case PECPU_ARMI: return "ARMI";
|
||||
case PECPU_ARMV7: return "ARMv7";
|
||||
case PECPU_EPOC: return "ARM EPOC";
|
||||
case PECPU_PPC: return "PPC";
|
||||
case PECPU_PPCFP: return "PPC FP";
|
||||
case PECPU_PPCBE: return "PPC BE";
|
||||
case PECPU_IA64: return "IA64";
|
||||
case PECPU_R3000: return "MIPS R3000";
|
||||
case PECPU_R4000: return "MIPS R4000";
|
||||
case PECPU_R6000: return "MIPS R6000";
|
||||
case PECPU_R10000: return "MIPS R10000";
|
||||
case PECPU_MIPS16: return "MIPS16";
|
||||
case PECPU_WCEMIPSV2: return "MIPS WCEv2";
|
||||
case PECPU_ALPHA: return "ALPHA";
|
||||
case PECPU_ALPHA64: return "ALPHA 64";
|
||||
case PECPU_AMD64: return "AMD64";
|
||||
case PECPU_ARM64: return "ARM64";
|
||||
case PECPU_M68K: return "M68K";
|
||||
case PECPU_MIPSFPU: return "MIPS FPU";
|
||||
case PECPU_MIPSFPU16: return "MIPS16 FPU";
|
||||
case PECPU_EBC: return "EFI Bytecode";
|
||||
case PECPU_AM33: return "AM33";
|
||||
case PECPU_M32R: return "M32R";
|
||||
case PECPU_CEF: return "CEF";
|
||||
case PECPU_CEE: return "CEE";
|
||||
case PECPU_TRICORE: return "TRICORE";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline bool pe_loader_t::read_strtable(qstring *out, linput_t *li)
|
||||
{
|
||||
bool ok = false;
|
||||
if ( pe.symtof != 0 )
|
||||
{
|
||||
qoff64_t strtoff = qoff64_t(pe.symtof) + pe.nsyms * 18;
|
||||
ok = read_string_table(out, li, strtoff);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
306
idasdk76/ldr/pe/common.h
Normal file
306
idasdk76/ldr/pe/common.h
Normal file
@@ -0,0 +1,306 @@
|
||||
#ifndef _PE_LDR_COMMON_H_
|
||||
#define _PE_LDR_COMMON_H_
|
||||
|
||||
#include <netnode.hpp>
|
||||
#include <idp.hpp>
|
||||
#include <loader.hpp>
|
||||
#include <diskio.hpp>
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
//------------------------------------------------------------------------
|
||||
struct pe_section_visitor_t
|
||||
{
|
||||
virtual int idaapi visit_section(const pesection_t &, off_t /*file_offset*/) { return 0; }
|
||||
virtual int idaapi load_all() { return 0; }
|
||||
virtual ~pe_section_visitor_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//-V:pe_import_visitor_t:730 not all members of a class are initialized inside the constructor
|
||||
struct pe_import_visitor_t
|
||||
{
|
||||
bool withbase;
|
||||
int elsize; // initialized by process_import_table()
|
||||
peimpdir_t id;
|
||||
dimpdir_t did;
|
||||
|
||||
pe_import_visitor_t(void) : withbase(false) {}
|
||||
virtual int idaapi visit_module(const char * /*dll*/, ea_t /*iat_start*/, ea_t /*int_rva*/) { return 0; }
|
||||
virtual int idaapi leave_module(uint32 /*nprocessed_imports*/) { return 0; }
|
||||
// buf==NULL:by ordinal
|
||||
virtual int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) = 0;
|
||||
virtual int idaapi impdesc_error(off_t /*file_offset*/) { return 0; }
|
||||
virtual ~pe_import_visitor_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct pe_export_visitor_t
|
||||
{
|
||||
// this function will be called once at the start.
|
||||
// it must return 0 to continue
|
||||
virtual int idaapi visit_expdir(const peexpdir_t & /*ed*/, const char * /*modname*/) { return 0; }
|
||||
// this function is called for each export. name is never NULL, forwarder may point to the forwarder function
|
||||
// it must return 0 to continue
|
||||
virtual int idaapi visit_export(uint32 rva, uint32 ord, const char *name, const char *forwarder) = 0;
|
||||
virtual ~pe_export_visitor_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class pe_loader_t
|
||||
{
|
||||
int process_import_table(
|
||||
linput_t *li,
|
||||
ea_t atable,
|
||||
ea_t ltable,
|
||||
pe_import_visitor_t &piv);
|
||||
template <class T>
|
||||
T varead(linput_t *li, uint32 rva, bool *ok)
|
||||
{
|
||||
T x = 0;
|
||||
bool _ok = vseek(li, rva) && qlread(li, &x, sizeof(x)) == sizeof(x);
|
||||
if ( ok != NULL )
|
||||
*ok = _ok;
|
||||
return x;
|
||||
}
|
||||
public:
|
||||
struct transl_t
|
||||
{
|
||||
ea_t start;
|
||||
ea_t end;
|
||||
off_t pos;
|
||||
size_t psize;
|
||||
};
|
||||
typedef qvector<transl_t> transvec_t;
|
||||
transvec_t transvec;
|
||||
union
|
||||
{
|
||||
exehdr exe;
|
||||
teheader_t te;
|
||||
};
|
||||
peheader_t pe;
|
||||
peheader64_t pe64; // original 64bit header, should not be used
|
||||
// because all fields are copied to pe
|
||||
// nb: imagebase is truncated during the copy!
|
||||
ea_t load_imagebase; // imagebase used during loading; initialized from the PE header but can be changed by the user
|
||||
off_t peoff; // offset to pe header
|
||||
bool link_ulink; // linked with unilink?
|
||||
|
||||
// low level functions
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// NB! We need to walk the mapping backwards, because
|
||||
// the later sections take priority over earlier ones
|
||||
//
|
||||
// e.g. consider
|
||||
// section 0: start=1000, end=5000, pos=1000
|
||||
// section 1: start=3000, end=4000, pos=5000
|
||||
// for byte at RVA 3500:
|
||||
// section 0 maps it from the file offset 3500
|
||||
// but section 1 overrides it with the byte from file offset 5500!
|
||||
//
|
||||
inline ea_t map_ea(ea_t rva, const transl_t **tl=NULL)
|
||||
{
|
||||
for ( ssize_t i=transvec.size()-1; i >= 0; i-- )
|
||||
{
|
||||
const transl_t &trans = transvec[i];
|
||||
if ( trans.start <= rva && trans.end > rva )
|
||||
{
|
||||
if ( tl != NULL )
|
||||
*tl = &trans;
|
||||
return rva-trans.start + trans.pos;
|
||||
}
|
||||
}
|
||||
return BADADDR;
|
||||
}
|
||||
ea_t get_imagebase(void) const { return load_imagebase; }
|
||||
void set_imagebase(ea_t newimagebase) { load_imagebase=newimagebase; }
|
||||
virtual bool vseek(linput_t *li, uint32 rva);
|
||||
inline uint16 vashort(linput_t *li, uint32 addr, bool *ok) { return varead<uint16>(li, addr, ok); }
|
||||
inline uint32 valong(linput_t *li, uint32 addr, bool *ok) { return varead<uint32>(li, addr, ok); }
|
||||
inline uint64 vaint64(linput_t *li, uint32 addr, bool *ok) { return varead<uint64>(li, addr, ok); }
|
||||
char *asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok);
|
||||
char *asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok);
|
||||
int process_sections(linput_t *li, off_t fist_sec_pos, int nojbs, pe_section_visitor_t &psv);
|
||||
int process_sections(linput_t *li, pe_section_visitor_t &psv);
|
||||
// If 'zero_bad_data==true' (i.e., the default), extra 'directories'
|
||||
// in the pe/pe64 headers will be set to zero.
|
||||
bool read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data = true);
|
||||
|
||||
// high level functions
|
||||
bool read_header(linput_t *li, bool silent=false, bool zero_bad_data = true);
|
||||
int process_sections(linput_t *li);
|
||||
|
||||
int process_delayed_imports(linput_t *li, pe_import_visitor_t &il);
|
||||
int process_imports(linput_t *li, pe_import_visitor_t &piv);
|
||||
int process_exports(linput_t *li, pe_export_visitor_t &pev);
|
||||
bool vmread(linput_t *li, uint32 rva, void *buf, size_t sz);
|
||||
|
||||
bool read_strtable(qstring *out, linput_t *li);
|
||||
|
||||
virtual ~pe_loader_t(void) {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct import_loader_t : public pe_import_visitor_t
|
||||
{
|
||||
struct dllinfo_t
|
||||
{
|
||||
qstring orig_name;
|
||||
qstring name;
|
||||
netnode node; // will be used by import_module()
|
||||
bool imported_module;
|
||||
|
||||
dllinfo_t()
|
||||
: imported_module(false)
|
||||
{}
|
||||
};
|
||||
typedef qvector<dllinfo_t> dllinfo_vec_t;
|
||||
|
||||
processor_t &ph;
|
||||
peheader_t &pe;
|
||||
dllinfo_vec_t dlls; // visited modules
|
||||
range_t imprange;
|
||||
ea_t astart;
|
||||
ea_t last_imp;
|
||||
ea_t int_rva;
|
||||
int ndid; // number of delayed import dirs
|
||||
bool displayed;
|
||||
bool got_new_imports;
|
||||
bool delayed_imports;
|
||||
|
||||
inline void preprocess(void);
|
||||
inline bool has_module(const char *mod) const
|
||||
{
|
||||
size_t ndlls = dlls.size();
|
||||
for ( size_t i = 0; i < ndlls; i++ )
|
||||
if ( !stricmp(dlls[i].orig_name.c_str(), mod) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
int idaapi visit_module(const char *dll, ea_t iat_start, ea_t _int_rva) override;
|
||||
int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) override;
|
||||
int idaapi leave_module(uint32 nprocessed_imports) override;
|
||||
int idaapi impdesc_error(off_t off) override;
|
||||
inline void postprocess(void);
|
||||
|
||||
import_loader_t(processor_t &_ph, peheader_t &_pe, bool di)
|
||||
: ph(_ph), pe(_pe), astart(BADADDR), last_imp(BADADDR), int_rva(0),
|
||||
ndid(0),
|
||||
displayed(false), got_new_imports(false), delayed_imports(di)
|
||||
{
|
||||
imprange.start_ea = BADADDR;
|
||||
imprange.end_ea = 0;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef __EA64__
|
||||
|
||||
struct function_entry_x64
|
||||
{
|
||||
uint32 BeginAddress;
|
||||
uint32 EndAddress;
|
||||
uint32 UnwindData;
|
||||
bool operator<(const function_entry_x64 &r) const { return BeginAddress < r.BeginAddress; }
|
||||
bool operator!=(const function_entry_x64 &r) const
|
||||
{
|
||||
return BeginAddress != r.BeginAddress
|
||||
|| EndAddress != r.EndAddress
|
||||
|| UnwindData != r.UnwindData;
|
||||
}
|
||||
};
|
||||
|
||||
struct unwind_info_x64
|
||||
{
|
||||
uint8 Version_Flags;
|
||||
uint8 SizeOfProlog; //lint -e754 local structure member not referenced
|
||||
uint8 CountOfCodes;
|
||||
uint8 FrameRegister_Offset;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct ida_loader_t : public pe_loader_t
|
||||
{
|
||||
processor_t &ph;
|
||||
eavec_t asked_eas;
|
||||
import_loader_t imploader; // used in load_imports()
|
||||
import_loader_t didloader; // used in load_delayed_imports()
|
||||
eavec_t imp_fixups; // fixups to the import tables,
|
||||
// they will be updated after a creation of
|
||||
// the .idata segment
|
||||
bool loaded_header = false;
|
||||
bool vseek_asked = false;
|
||||
bool has_embedded_pdb = false;
|
||||
|
||||
virtual bool vseek(linput_t *li, uint32 rva) override
|
||||
{
|
||||
ea_t fpos;
|
||||
if ( get_linput_type(li) == LINPUT_PROCMEM )
|
||||
{
|
||||
fpos = rva;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpos = map_ea(rva);
|
||||
if ( fpos == BADADDR && rva < peoff+pe.allhdrsize )
|
||||
fpos = rva;
|
||||
}
|
||||
if ( fpos != BADADDR )
|
||||
{
|
||||
qoff64_t p2 = qlseek(li, qoff64_t(fpos));
|
||||
return p2 != -1;
|
||||
}
|
||||
if ( !vseek_asked
|
||||
&& ask_yn(ASKBTN_YES,
|
||||
"HIDECANCEL\n"
|
||||
"Can't find translation for relative virtual address %08X, continue?",
|
||||
rva) <= ASKBTN_NO )
|
||||
{
|
||||
loader_failure();
|
||||
}
|
||||
vseek_asked = true;
|
||||
qlseek(li, rva, SEEK_SET);
|
||||
return false;
|
||||
}
|
||||
ida_loader_t(void) //lint !e1401 non-static data member 'pe_loader_t::*' not initialized by constructor
|
||||
: ph(PH),
|
||||
imploader(ph, pe, false),
|
||||
didloader(ph, pe, true) {}
|
||||
|
||||
void setup_entry_and_dgroup(linput_t *li, sel_t dgroup);
|
||||
bool make_beginning_loaded(linput_t *li, ea_t begin);
|
||||
sel_t load_sections(linput_t *li, bool aux, const qstring *strtable=nullptr);
|
||||
void load_tls(linput_t *li);
|
||||
void load_exports(linput_t *li);
|
||||
void load_imports(linput_t *li);
|
||||
void load_delayed_imports(linput_t *li);
|
||||
void read_and_save_fixups(linput_t *li);
|
||||
bool has_imports_by_ordinal(linput_t *li);
|
||||
void load_cli_module(linput_t *_li);
|
||||
void load_pdata(linput_t *li);
|
||||
void pe_convert_idata();
|
||||
void comment_impexp(linput_t *li);
|
||||
void load_loadconfig(linput_t *li);
|
||||
void load_header_section(linput_t *li, bool visible);
|
||||
void load_debug_info(linput_t *li);
|
||||
void remember_imp_fixup(ea_t fixup_ea, ea_t target)
|
||||
{
|
||||
for ( const auto &impldr : { imploader, didloader } )
|
||||
{
|
||||
if ( impldr.imprange.contains(target) )
|
||||
{
|
||||
imp_fixups.add(fixup_ea);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool has_ntdll() const { return imploader.has_module("ntdll.dll"); }
|
||||
#ifdef __EA64__
|
||||
int check_chained_uw(linput_t *li, uint32 rva, function_entry_x64 *chained, int nest_count = 0);
|
||||
void load_pdata_x64(linput_t *li, uint32 pdata_rva, asize_t psize);
|
||||
bool has_bad_uwopcodes(linput_t *li, uint32 uw_rva, ea_t funcstart);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
2532
idasdk76/ldr/pe/cor.h
Normal file
2532
idasdk76/ldr/pe/cor.h
Normal file
File diff suppressed because it is too large
Load Diff
1845
idasdk76/ldr/pe/corhdr.h
Normal file
1845
idasdk76/ldr/pe/corhdr.h
Normal file
File diff suppressed because it is too large
Load Diff
507
idasdk76/ldr/pe/mycor.h
Normal file
507
idasdk76/ldr/pe/mycor.h
Normal file
@@ -0,0 +1,507 @@
|
||||
// Borland-compatible Microsoft.Net definitions
|
||||
// Only the most important headers are declared
|
||||
//
|
||||
// The second half of the file contains the structures saved in the
|
||||
// database
|
||||
|
||||
#ifndef __MYCOR_H
|
||||
#define __MYCOR_H
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#ifdef __NT__
|
||||
typedef wchar_t wchar;
|
||||
#else
|
||||
typedef wchar16_t wchar;
|
||||
#endif
|
||||
|
||||
#ifndef _WINDOWS_ // define some MS Windows symbols if <windows.h> is not included
|
||||
|
||||
#define __int8 char
|
||||
#ifdef __GNUC__
|
||||
#define __cdecl
|
||||
#define __stdcall
|
||||
#endif
|
||||
|
||||
typedef int32 HRESULT;
|
||||
#define S_OK 0
|
||||
#define S_FALSE (!S_OK)
|
||||
#define E_FAIL 0x80004005
|
||||
#define SEVERITY_SUCCESS 0
|
||||
#define SEVERITY_ERROR 1
|
||||
#define FACILITY_URT 19
|
||||
#define MAKE_HRESULT(sev,fac,code) \
|
||||
((HRESULT) (((uint32)(sev)<<31) | ((uint32)(fac)<<16) | ((uint32)(code))) )
|
||||
#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)
|
||||
#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)
|
||||
#define META_E_BAD_SIGNATURE EMAKEHR(0x1192) // Bad binary signature
|
||||
#define FAILED(hr) (((HRESULT)(hr)) < 0)
|
||||
#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
|
||||
#undef UNALIGNED
|
||||
#define UNALIGNED
|
||||
|
||||
typedef uchar BYTE;
|
||||
typedef short SHORT;
|
||||
typedef ushort USHORT;
|
||||
typedef ushort WORD;
|
||||
typedef uint32 ULONG;
|
||||
typedef uint ULONG32;
|
||||
typedef uint32 DWORD;
|
||||
typedef uint64 DWORD64;
|
||||
typedef void *LPVOID;
|
||||
typedef bool BOOL;
|
||||
typedef int32 LONG;
|
||||
typedef uint32 ULONG;
|
||||
typedef int64 LONGLONG;
|
||||
typedef uint64 ULONGLONG;
|
||||
typedef wchar *LPWSTR;
|
||||
typedef const void *UVCP_CONSTANT;
|
||||
typedef ULONG &LPCWSTR;
|
||||
typedef float FLOAT;
|
||||
typedef double DOUBLE;
|
||||
typedef uint32 SCODE;
|
||||
typedef void *BSTR; // http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069(v=vs.85).aspx
|
||||
typedef void *PVOID;
|
||||
typedef int INT;
|
||||
typedef uint UINT;
|
||||
typedef char CHAR;
|
||||
typedef DOUBLE DATE;
|
||||
|
||||
class IUnknown;
|
||||
|
||||
struct OSINFO
|
||||
{
|
||||
DWORD dwOSPlatformId;
|
||||
DWORD dwOSMajorVersion;
|
||||
DWORD dwOSMinorVersion;
|
||||
};
|
||||
|
||||
struct ASSEMBLYMETADATA
|
||||
{
|
||||
USHORT usMajorVersion;
|
||||
USHORT usMinorVersion;
|
||||
USHORT usBuildNumber;
|
||||
USHORT usRevisionNumber;
|
||||
LPWSTR szLocale;
|
||||
ULONG cbLocale;
|
||||
DWORD *rdwProcessor;
|
||||
ULONG ulProcessor;
|
||||
OSINFO *rOS;
|
||||
ULONG ulOS;
|
||||
};
|
||||
|
||||
struct GUID
|
||||
{
|
||||
uint32 Data1;
|
||||
ushort Data2;
|
||||
ushort Data3;
|
||||
uchar Data4[8];
|
||||
};
|
||||
|
||||
struct IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
uint32 VirtualAddress;
|
||||
uint32 Size;
|
||||
};
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221061(v=vs.85).aspx
|
||||
typedef struct tagDEC
|
||||
{
|
||||
USHORT wReserved;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE scale;
|
||||
BYTE sign;
|
||||
};
|
||||
USHORT signscale;
|
||||
};
|
||||
ULONG Hi32;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG Lo32;
|
||||
ULONG Mid32;
|
||||
};
|
||||
ULONGLONG Lo64;
|
||||
};
|
||||
} DECIMAL;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221223(v=vs.85).aspx
|
||||
typedef union tagCY
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned long Lo;
|
||||
long Hi;
|
||||
};
|
||||
LONGLONG int64;
|
||||
} CY, CURRENCY;
|
||||
|
||||
|
||||
typedef struct tagSAFEARRAYBOUND
|
||||
{
|
||||
ULONG cElements;
|
||||
LONG lLbound;
|
||||
} SAFEARRAYBOUND, *LPSAFEARRAYBOUND;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/9ec8025b-4763-4526-ab45-390c5d8b3b1e(VS.85)
|
||||
typedef struct tagSAFEARRAY
|
||||
{
|
||||
USHORT cDims;
|
||||
USHORT fFeatures;
|
||||
ULONG cbElements;
|
||||
ULONG cLocks;
|
||||
PVOID pvData;
|
||||
SAFEARRAYBOUND rgsabound[1];
|
||||
} SAFEARRAY, *LPSAFEARRAY;
|
||||
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms221627(v=vs.85).aspx
|
||||
typedef unsigned short VARTYPE;
|
||||
typedef uint16 VARIANT_BOOL;
|
||||
typedef uint16 _VARIANT_BOOL;
|
||||
struct IRecordInfo;
|
||||
typedef struct tagVARIANT
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
VARTYPE vt;
|
||||
WORD wReserved1;
|
||||
WORD wReserved2;
|
||||
WORD wReserved3;
|
||||
union
|
||||
{
|
||||
LONGLONG llVal;
|
||||
LONG lVal;
|
||||
BYTE bVal;
|
||||
SHORT iVal;
|
||||
FLOAT fltVal;
|
||||
DOUBLE dblVal;
|
||||
VARIANT_BOOL boolVal;
|
||||
/* _VARIANT_BOOL bool; */
|
||||
SCODE scode;
|
||||
CY cyVal;
|
||||
DATE date;
|
||||
BSTR bstrVal;
|
||||
IUnknown *punkVal;
|
||||
/* IDispatch *pdispVal; */
|
||||
SAFEARRAY *parray;
|
||||
BYTE *pbVal;
|
||||
SHORT *piVal;
|
||||
LONG *plVal;
|
||||
LONGLONG *pllVal;
|
||||
FLOAT *pfltVal;
|
||||
DOUBLE *pdblVal;
|
||||
VARIANT_BOOL *pboolVal;
|
||||
/* _VARIANT_BOOL *pbool; */
|
||||
SCODE *pscode;
|
||||
CY *pcyVal;
|
||||
DATE *pdate;
|
||||
BSTR *pbstrVal;
|
||||
/* IUnknown **ppunkVal; */
|
||||
/* IDispatch **ppdispVal; */
|
||||
SAFEARRAY **pparray;
|
||||
/* VARIANT *pvarVal; */
|
||||
PVOID byref;
|
||||
CHAR cVal;
|
||||
USHORT uiVal;
|
||||
ULONG ulVal;
|
||||
ULONGLONG ullVal;
|
||||
INT intVal;
|
||||
UINT uintVal;
|
||||
DECIMAL *pdecVal;
|
||||
CHAR *pcVal;
|
||||
USHORT *puiVal;
|
||||
ULONG *pulVal;
|
||||
ULONGLONG *pullVal;
|
||||
INT *pintVal;
|
||||
UINT *puintVal;
|
||||
struct /*__tagBRECORD*/
|
||||
{
|
||||
PVOID pvRecord;
|
||||
IRecordInfo *pRecInfo;
|
||||
} /* __VARIANT_NAME_4*/;
|
||||
} /* __VARIANT_NAME_3*/;
|
||||
} /* __VARIANT_NAME_2*/;
|
||||
DECIMAL decVal;
|
||||
};
|
||||
} VARIANT, *LPVARIANT, VARIANTARG, *LPVARIANTARG;
|
||||
|
||||
#define VT_EMPTY 0x0000
|
||||
#define VT_NULL 0x0001
|
||||
#define VT_I2 0x0002
|
||||
#define VT_I4 0x0003
|
||||
#define VT_R4 0x0004
|
||||
#define VT_R8 0x0005
|
||||
#define VT_CY 0x0006
|
||||
#define VT_DATE 0x0007
|
||||
#define VT_BSTR 0x0008
|
||||
#define VT_DISPATCH 0x0009
|
||||
#define VT_ERROR 0x000A
|
||||
#define VT_BOOL 0x000B
|
||||
#define VT_VARIANT 0x000C
|
||||
#define VT_UNKNOWN 0x000D
|
||||
#define VT_DECIMAL 0x000E
|
||||
#define VT_I1 0x0010
|
||||
#define VT_UI1 0x0011
|
||||
#define VT_UI2 0x0012
|
||||
#define VT_UI4 0x0013
|
||||
#define VT_I8 0x0014
|
||||
#define VT_UI8 0x0015
|
||||
#define VT_INT 0x0016
|
||||
#define VT_UINT 0x0017
|
||||
#define VT_VOID 0x0018
|
||||
#define VT_HRESULT 0x0019
|
||||
#define VT_PTR 0x001A
|
||||
#define VT_SAFEARRAY 0x001B
|
||||
#define VT_CARRAY 0x001C
|
||||
#define VT_USERDEFINED 0x001D
|
||||
#define VT_LPSTR 0x001E
|
||||
#define VT_LPWSTR 0x001F
|
||||
#define VT_RECORD 0x0024
|
||||
#define VT_INT_PTR 0x0025
|
||||
#define VT_UINT_PTR 0x0026
|
||||
#define VT_ARRAY 0x2000
|
||||
#define VT_BYREF 0x4000
|
||||
|
||||
|
||||
|
||||
#define VariantInit(v_ptr) (v_ptr)->vt = VT_EMPTY
|
||||
|
||||
inline HRESULT VariantClear(VARIANTARG *pVar)
|
||||
{
|
||||
memset(pVar, 0, sizeof(VARIANT));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
|
||||
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
|
||||
|
||||
|
||||
#define CLDB_S_TRUNCATION SMAKEHR(0x1106)
|
||||
#define CLDB_E_TRUNCATION EMAKEHR(0x1106)
|
||||
|
||||
|
||||
#endif // __UNIX__
|
||||
|
||||
#include "corhdr.h"
|
||||
#include "cor.h"
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// what netnode tag
|
||||
#define CLITAG_MDA 0 // the assembly mda is here at index 0
|
||||
#define CLITAG_MTK 1 // the scope mtk is here at index 0
|
||||
#define CLITAG_STRUCT 'a' // the structure itself is saved here
|
||||
#define CLITAG_NAME 'b' // char *name (deprecated for strings, see CLITAG_STRING)
|
||||
// saved as blob
|
||||
#define CLITAG_VALUE 'c' // void *pval
|
||||
#define CLITAG_SIG 'd' // PCOR_SIGNATURE[]
|
||||
#define CLITAG_OTHER 'e' // mdToken others[]
|
||||
//#define CLITAG_TITLE 'f' // assembly title
|
||||
//#define CLITAG_DESCR 'g' // assembly description
|
||||
//#define CLITAG_ALIAS 'h' // assembly alias
|
||||
#define CLITAG_PUBKEY 'i' // public key blob
|
||||
#define CLITAG_PINV 'k' // pinvoke_info_t
|
||||
#define CLITAG_PNAME 'l' // name of pinvoke method
|
||||
#define CLITAG_LAYOUT 'm' // layout_info_t
|
||||
#define CLITAG_OFFSETS 'n' // COR_FIELD_OFFSET[]
|
||||
#define CLITAG_CUST 'o' // custom attribute blob
|
||||
#define CLITAG_TOKEN 'p' // ea: method, field, property, event token is here
|
||||
#define CLITAG_CLASS 'q' // ea: typedef token
|
||||
#define CLITAG_STRING 'r' // ea: address of string's bytes in .strings segment
|
||||
#define CLITAG_CLASSEND 's' // ea: typedef token
|
||||
#define CLITAG_TRY 't' // ea: try block start/cor_exception_info_t
|
||||
#define CLITAG_BEND 'u' // ea: block end
|
||||
#define CLITAG_HASH 'v' // hash
|
||||
#define CLITAG_FRVA 'x' // field rva
|
||||
#define CLITAG_EXCEPTION 128 // exception blocks: several indexes
|
||||
|
||||
// enumeration blobs
|
||||
// global enumerations have index 0
|
||||
#define CLITAG_PARAMS 'A'
|
||||
#define CLITAG_FIELDS 'B'
|
||||
#define CLITAG_METHODS 'C'
|
||||
#define CLITAG_EVENTS 'D'
|
||||
#define CLITAG_PROPERTIES 'E'
|
||||
#define CLITAG_INTERFACES 'F'
|
||||
#define CLITAG_TYPEDEFS 'G'
|
||||
#define CLITAG_TYPEREFS 'H'
|
||||
#define CLITAG_TYPESPECS 'I'
|
||||
#define CLITAG_USERSTRINGS 'J'
|
||||
#define CLITAG_CUSTATTRS 'K'
|
||||
#define CLITAG_MODULEREFS 'L'
|
||||
#define CLITAG_MEMBERREFS 'M' // 'N' shouldn't be used (as well as 'V')
|
||||
|
||||
|
||||
struct param_info_t // +name +value
|
||||
{
|
||||
mdToken method;
|
||||
ULONG n;
|
||||
ULONG flags;
|
||||
DWORD deftype;
|
||||
};
|
||||
|
||||
struct field_info_t // +name +sig +value
|
||||
{
|
||||
mdToken owner;
|
||||
ULONG flags;
|
||||
DWORD deftype;
|
||||
ea_t ea;
|
||||
};
|
||||
|
||||
struct method_info_t // +name +sig +params
|
||||
{
|
||||
mdToken owner;
|
||||
DWORD flags;
|
||||
ULONG rva; // ea later
|
||||
DWORD implflags;
|
||||
mdToken lvars;
|
||||
uint32 maxstack;
|
||||
uint32 methodflags;
|
||||
};
|
||||
|
||||
struct pinvoke_info_t // +pname
|
||||
{
|
||||
DWORD mappingflags;
|
||||
mdToken dlltok;
|
||||
};
|
||||
|
||||
struct property_info_t // +name +sig +other_tokens +value
|
||||
{
|
||||
mdToken owner;
|
||||
ULONG flags;
|
||||
DWORD deftype;
|
||||
mdToken setter, getter;
|
||||
// mdToken backing; disappeared in Beta2
|
||||
ea_t ea;
|
||||
};
|
||||
|
||||
struct event_info_t // +name +other_tokens
|
||||
{
|
||||
mdToken owner;
|
||||
ULONG flags;
|
||||
mdToken type;
|
||||
mdToken addon, removeon, fire;
|
||||
ea_t ea;
|
||||
};
|
||||
|
||||
struct interfaceimpl_info_t
|
||||
{
|
||||
mdToken inttok;
|
||||
};
|
||||
|
||||
struct typedef_info_t // +name +fields +methods +layout +offsets
|
||||
{
|
||||
DWORD flags;
|
||||
mdToken super;
|
||||
};
|
||||
|
||||
struct layout_info_t
|
||||
{
|
||||
DWORD packsize;
|
||||
ULONG classsize;
|
||||
ULONG noffsets;
|
||||
};
|
||||
|
||||
struct typeref_info_t // +name
|
||||
{
|
||||
mdToken scope;
|
||||
};
|
||||
|
||||
struct moduleref_info_t // +name
|
||||
{
|
||||
};
|
||||
|
||||
struct memberref_info_t // +name +sig
|
||||
{
|
||||
mdToken owner;
|
||||
};
|
||||
|
||||
struct typespec_info_t // +sig
|
||||
{
|
||||
};
|
||||
|
||||
struct userstring_info_t // +name
|
||||
{
|
||||
};
|
||||
|
||||
struct custattr_info_t // +blob
|
||||
{
|
||||
mdToken owner;
|
||||
mdToken type;
|
||||
};
|
||||
|
||||
struct assembly_info_t // +name +orig +title +desc +alias
|
||||
{
|
||||
ULONG hash;
|
||||
DWORD flags;
|
||||
USHORT usMajorVersion;
|
||||
USHORT usMinorVersion;
|
||||
USHORT usRevisionNumber;
|
||||
USHORT usBuildNumber;
|
||||
};
|
||||
|
||||
struct assemblyref_info_t // +name +orig +hash
|
||||
{
|
||||
DWORD flags;
|
||||
// mdToken exeloc;
|
||||
USHORT usMajorVersion;
|
||||
USHORT usMinorVersion;
|
||||
USHORT usRevisionNumber;
|
||||
USHORT usBuildNumber;
|
||||
};
|
||||
|
||||
struct file_info_t // +name +hash
|
||||
{
|
||||
DWORD flags;
|
||||
};
|
||||
|
||||
struct comtype_info_t // +name +descr
|
||||
{
|
||||
ULONG flags;
|
||||
mdToken impl, type, exeloc;
|
||||
};
|
||||
|
||||
struct cor_module_info_t // +name
|
||||
{
|
||||
mdToken mtk;
|
||||
GUID mid;
|
||||
};
|
||||
|
||||
struct cor_exception_info_t
|
||||
{
|
||||
ULONG flags;
|
||||
ULONG param;
|
||||
};
|
||||
|
||||
struct longname_director_t
|
||||
{
|
||||
char zero;
|
||||
uval_t node;
|
||||
};
|
||||
CASSERT(sizeof(longname_director_t) == 1 + sizeof(uval_t));
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t get_free_address(void);
|
||||
void expand(ea_t ea);
|
||||
void define_class(mdToken, const char *name, ea_t ea1, ea_t ea2);
|
||||
mdToken define_method(mdToken method, const char *name, method_info_t &b, ea_t *ea);
|
||||
void supset(ea_t idx, const void *body, int size, char tag);
|
||||
ssize_t supstr(ea_t idx, char *buf, size_t bufsize, char tag);
|
||||
void altset(ea_t idx, ea_t val, char tag);
|
||||
void setblob(ea_t idx, const void *body, int size, char tag);
|
||||
void save_name(ea_t idx, const qstring &name);
|
||||
qstring retrieve_name(ea_t idx);
|
||||
uint32 get_constant_element_type_raw_size(CorElementType type, uint32 chars);
|
||||
|
||||
bool load_metadata(const void *metadata, size_t metasize);
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // define __MYCOR_H
|
||||
1174
idasdk76/ldr/pe/pe.h
Normal file
1174
idasdk76/ldr/pe/pe.h
Normal file
File diff suppressed because it is too large
Load Diff
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
|
||||
144
idasdk76/ldr/pilot/common.cpp
Normal file
144
idasdk76/ldr/pilot/common.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static void swap_prc(DatabaseHdrType &h)
|
||||
{
|
||||
h.attributes = swap16(h.attributes);
|
||||
h.version = swap16(h.version);
|
||||
h.creationDate = swap32(h.creationDate);
|
||||
h.modificationDate = swap32(h.modificationDate);
|
||||
h.lastBackupDate = swap32(h.lastBackupDate);
|
||||
h.modificationNumber = swap32(h.modificationNumber);
|
||||
h.appInfoID = swap32(h.appInfoID);
|
||||
h.sortInfoID = swap32(h.sortInfoID);
|
||||
// h.type = swap32(h.type);
|
||||
// h.id = swap32(h.id);
|
||||
h.uniqueIDSeed = swap32(h.uniqueIDSeed);
|
||||
h.nextRecordListID = swap32(h.nextRecordListID);
|
||||
h.numRecords = swap16(h.numRecords);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static void swap_resource_map_entry(ResourceMapEntry &re)
|
||||
{
|
||||
re.id = swap16(re.id);
|
||||
re.ulOffset = swap32(re.ulOffset);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void swap_bitmap(pilot_bitmap_t *b)
|
||||
{
|
||||
b->cx = swap16(b->cx);
|
||||
b->cy = swap16(b->cy);
|
||||
b->cbRow = swap16(b->cbRow);
|
||||
b->ausUnk[0] = swap16(b->ausUnk[0]);
|
||||
b->ausUnk[1] = swap16(b->ausUnk[1]);
|
||||
b->ausUnk[2] = swap16(b->ausUnk[2]);
|
||||
b->ausUnk[3] = swap16(b->ausUnk[3]);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void swap_code0000(code0000_t *cp)
|
||||
{
|
||||
cp->nBytesAboveA5 = swap32(cp->nBytesAboveA5);
|
||||
cp->nBytesBelowA5 = swap32(cp->nBytesBelowA5);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void swap_pref0000(pref0000_t *pp)
|
||||
{
|
||||
pp->flags = swap16(pp->flags);
|
||||
pp->stack_size = swap32(pp->stack_size);
|
||||
pp->heap_size = swap32(pp->heap_size);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Since the Palm Pilot programs are really poorly recognized by usual
|
||||
// methods, we are forced to read the resource tablee to determine
|
||||
// if everying is ok
|
||||
// return 0 if not a PRC, 2 if has ARM code segments, 1 otherwise
|
||||
int is_prc_file(linput_t *li)
|
||||
{
|
||||
DatabaseHdrType h;
|
||||
if ( qlread(li,&h,sizeof(h)) != sizeof(h) )
|
||||
return 0;
|
||||
swap_prc(h);
|
||||
if ( (h.attributes & dmHdrAttrResDB) == 0 )
|
||||
return 0;
|
||||
if ( short(h.numRecords) <= 0 )
|
||||
return 0;
|
||||
const uint64 filesize = qlsize(li);
|
||||
const uint64 lowestpos = uint64(h.numRecords)*sizeof(ResourceMapEntry) + sizeof(h);
|
||||
if ( lowestpos > filesize )
|
||||
return 0;
|
||||
|
||||
// the dates can be plain wrong, so don't check them:
|
||||
// uint32 now = time(NULL);
|
||||
// && uint32(h.lastBackupDate) <= now // use unsigned comparition!
|
||||
// && uint32(h.creationDate) <= now // use unsigned comparition!
|
||||
// && uint32(h.modificationDate) <= now // use unsigned comparition!
|
||||
|
||||
qvector<ResourceMapEntry> re;
|
||||
re.resize(h.numRecords);
|
||||
size_t size = sizeof(ResourceMapEntry) * h.numRecords;
|
||||
if ( qlread(li, re.begin(), size) != size )
|
||||
return 0;
|
||||
|
||||
bool hasArmCode = false;
|
||||
for ( int i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
swap_resource_map_entry(re[i]);
|
||||
if ( re[i].ulOffset >= filesize || re[i].ulOffset < lowestpos )
|
||||
return 0;
|
||||
if ( re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL )
|
||||
hasArmCode = true;
|
||||
}
|
||||
return hasArmCode ? 2 : 1;
|
||||
}
|
||||
|
||||
bool isKnownResource(uint32 resId)
|
||||
{
|
||||
switch ( resId )
|
||||
{
|
||||
case MC4('t', 'F', 'R', 'M'):
|
||||
case MC4('t', 'B', 'T', 'N'):
|
||||
case MC4('t', 'C', 'B', 'X'):
|
||||
case MC4('t', 'F', 'B', 'M'):
|
||||
case MC4('t', 'F', 'L', 'D'):
|
||||
case MC4('t', 'g', 'b', 'n'):
|
||||
case MC4('t', 'G', 'D', 'T'):
|
||||
case MC4('t', 'g', 'p', 'b'):
|
||||
case MC4('t', 'g', 'r', 'b'):
|
||||
case MC4('t', 'G', 'S', 'I'):
|
||||
case MC4('t', 'L', 'B', 'L'):
|
||||
case MC4('t', 'L', 'S', 'T'):
|
||||
case MC4('t', 'P', 'B', 'N'):
|
||||
case MC4('t', 'P', 'U', 'L'):
|
||||
case MC4('t', 'P', 'U', 'T'):
|
||||
case MC4('t', 'R', 'E', 'P'):
|
||||
case MC4('t', 'S', 'C', 'L'):
|
||||
case MC4('t', 's', 'l', 'd'):
|
||||
case MC4('t', 's', 'l', 'f'):
|
||||
case MC4('t', 'S', 'L', 'T'):
|
||||
case MC4('t', 'T', 'B', 'L'):
|
||||
case MC4('T', 'a', 'l', 't'):
|
||||
case MC4('M', 'B', 'A', 'R'):
|
||||
case MC4('M', 'E', 'N', 'U'):
|
||||
case MC4('t', 'S', 'T', 'R'):
|
||||
case MC4('t', 'S', 'T', 'L'):
|
||||
case MC4('T', 'b', 'm', 'p'):
|
||||
case MC4('t', 'b', 'm', 'f'):
|
||||
case MC4('P', 'I', 'C', 'T'):
|
||||
case MC4('t', 'v', 'e', 'r'):
|
||||
case MC4('t', 'A', 'I', 'N'):
|
||||
case MC4('t', 'a', 'i', 'c'):
|
||||
case MC4('t', 'A', 'I', 'S'):
|
||||
case MC4('t', 'A', 'I', 'B'):
|
||||
case MC4('t', 'a', 'i', 'f'):
|
||||
case MC4('I', 'C', 'O', 'N'):
|
||||
case MC4('c', 'i', 'c', 'n'):
|
||||
case MC4('p', 'r', 'e', 'f'):
|
||||
case MC4('x', 'p', 'r', 'f'):
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
14
idasdk76/ldr/pilot/makefile
Normal file
14
idasdk76/ldr/pilot/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=pilot
|
||||
IDCS=pilot.idc
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)pilot$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)expr.hpp \
|
||||
$(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \
|
||||
$(I)xref.hpp ../idaldr.h common.cpp pilot.cpp pilot.hpp
|
||||
912
idasdk76/ldr/pilot/pilot.cpp
Normal file
912
idasdk76/ldr/pilot/pilot.cpp
Normal file
@@ -0,0 +1,912 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include <expr.hpp>
|
||||
#include "pilot.hpp"
|
||||
|
||||
#include "common.cpp"
|
||||
//------------------------------------------------------------------------
|
||||
static void describe_all(DatabaseHdrType &h)
|
||||
{
|
||||
create_filename_cmt();
|
||||
add_pgm_cmt("Version : %04X",h.version);
|
||||
add_pgm_cmt("DatabaseType: %4.4s",(char*)&h.type);
|
||||
add_pgm_cmt("\n appl \"%s\", '%4.4s'", h.name, (char*)&h.id);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
// Structure of the DATA 0 resource:
|
||||
//
|
||||
// +--------------------------------------------+
|
||||
// | long: offset of CODE 1 xrefs? |- -+
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: Initialized near data (below A5) | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: Uninitialized near data (below A5) | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: Initialized far data (above A5) | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: DATA 0 xrefs | |
|
||||
// +--------------------------------------------+ |
|
||||
// | char[]: CODE 1 xrefs |<--+
|
||||
// +--------------------------------------------+
|
||||
//
|
||||
|
||||
static uchar *apply_relocs(uchar *packed, size_t &packlen, ea_t relocbase, ea_t targetbase, bool code=false)
|
||||
{
|
||||
if ( packlen < 4 )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return NULL;
|
||||
}
|
||||
uint32 nrelocs = swap32(*(uint32*)packed);
|
||||
packed += 4;
|
||||
packlen -= 4;
|
||||
ea_t offset = relocbase;
|
||||
fixup_data_t fd(FIXUP_OFF32);
|
||||
if ( code )
|
||||
fd.set_sel(getseg(targetbase));
|
||||
//msg("%d relocations\n", nrelocs);
|
||||
for ( uint i=0; i < nrelocs; i++ )
|
||||
{
|
||||
if ( packlen < 1 )
|
||||
goto BADDATA;
|
||||
uchar c = *packed;
|
||||
if ( c&0x80 )
|
||||
{
|
||||
// signed 8-bit delta
|
||||
offset+=(char)(c<<1);
|
||||
packed++;
|
||||
packlen--;
|
||||
}
|
||||
else if ( c&0x40 )
|
||||
{
|
||||
if ( packlen < 2 )
|
||||
goto BADDATA;
|
||||
// 15-bit unsigned(?) delta
|
||||
// comment in PalmOS_Startup.cpp says "unsigned" but they cast it to a signed short...
|
||||
uint32 o1 = swap16(*(ushort*)packed);
|
||||
packed += 2;
|
||||
packlen -= 2;
|
||||
offset += (short)(o1<<2)>>1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( packlen < 4 )
|
||||
goto BADDATA;
|
||||
// direct signed 31-bit offset
|
||||
offset = relocbase+(int32(swap32(*(int32*)packed)<<2)>>1);
|
||||
packed += 4;
|
||||
packlen -= 4;
|
||||
}
|
||||
for ( int j=0; j < 4; j++ )
|
||||
if ( !is_loaded(offset+j) )
|
||||
put_byte(offset+j, 0);
|
||||
fd.off = get_dword(offset);
|
||||
if ( code )
|
||||
{
|
||||
fd.set(offset);
|
||||
auto_make_proc(targetbase+fd.off);
|
||||
if ( get_word(offset-2) == 0x4EF9 ) // jump opcode?
|
||||
auto_make_proc(offset-2);
|
||||
}
|
||||
else
|
||||
{
|
||||
fd.set_base(targetbase);
|
||||
fd.set(offset);
|
||||
}
|
||||
// msg("Relocation %d at %08X: %08X -> %08X\n", i, offset-relocbase, fd.off, targetbase+fd.off);
|
||||
}
|
||||
return packed;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// unpack rle data from the buffer packed at file position fpos to ea cea
|
||||
// return new position in the buffer and update cea
|
||||
static uchar *unpack_rle(uchar *packed, size_t &packlen, ea_t &cea, qoff64_t fpos)
|
||||
{
|
||||
const uchar *packed_sav = packed;
|
||||
while ( 1 )
|
||||
{
|
||||
if ( packlen < 1 )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return NULL;
|
||||
}
|
||||
uchar buf[256];
|
||||
buf[0] = '\0'; // shutup lint
|
||||
uchar cnt = *packed++;
|
||||
packlen--;
|
||||
if ( cnt == 0 )
|
||||
break;
|
||||
if ( cnt & 0x80 )
|
||||
{
|
||||
cnt = (cnt & 0x7F) + 1;
|
||||
if ( packlen < cnt )
|
||||
goto BADDATA;
|
||||
mem2base(packed, cea, cea+cnt, fpos+(packed-packed_sav));
|
||||
packed += cnt;
|
||||
packlen -= cnt;
|
||||
cea += cnt;
|
||||
continue;
|
||||
}
|
||||
if ( cnt & 0x40 )
|
||||
{
|
||||
cnt = (cnt & 0x3F) + 1;
|
||||
memset(buf, 0, cnt);
|
||||
}
|
||||
else if ( cnt & 0x20 )
|
||||
{
|
||||
if ( packlen < 1 )
|
||||
goto BADDATA;
|
||||
cnt = (cnt & 0x1F) + 2;
|
||||
memset(buf, *packed++, cnt);
|
||||
packlen--;
|
||||
}
|
||||
else if ( cnt & 0x10 )
|
||||
{
|
||||
cnt = (cnt & 0x0F) + 1;
|
||||
memset(buf, 0xFF, cnt);
|
||||
}
|
||||
else if ( cnt == 1 )
|
||||
{
|
||||
if ( packlen < 2 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0xFF;
|
||||
buf[5] = 0xFF;
|
||||
buf[6] = *packed++;
|
||||
buf[7] = *packed++;
|
||||
packlen -= 2;
|
||||
cnt = 8;
|
||||
}
|
||||
else if ( cnt == 2 )
|
||||
{
|
||||
if ( packlen < 3 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0x00;
|
||||
buf[1] = 0x00;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = 0xFF;
|
||||
buf[5] = *packed++;
|
||||
buf[6] = *packed++;
|
||||
buf[7] = *packed++;
|
||||
cnt = 8;
|
||||
packlen -= 3;
|
||||
}
|
||||
else if ( cnt == 3 )
|
||||
{
|
||||
if ( packlen < 3 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0xA9;
|
||||
buf[1] = 0xF0;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = *packed++;
|
||||
buf[5] = *packed++;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = *packed++;
|
||||
cnt = 8;
|
||||
packlen -= 3;
|
||||
}
|
||||
else if ( cnt == 4 )
|
||||
{
|
||||
if ( packlen < 4 )
|
||||
goto BADDATA;
|
||||
buf[0] = 0xA9;
|
||||
buf[1] = 0xF0;
|
||||
buf[2] = 0x00;
|
||||
buf[3] = *packed++;
|
||||
buf[4] = *packed++;
|
||||
buf[5] = *packed++;
|
||||
buf[6] = 0x00;
|
||||
buf[7] = *packed++;
|
||||
cnt = 8;
|
||||
packlen -= 4;
|
||||
}
|
||||
mem2base(buf, cea, cea+cnt, -1);
|
||||
cea += cnt;
|
||||
}
|
||||
return packed;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static size_t unpack_data0000(
|
||||
linput_t *li,
|
||||
qoff64_t fpos,
|
||||
size_t size,
|
||||
ea_t ea,
|
||||
const code0000_t &code0000,
|
||||
ea_t code1ea,
|
||||
ea_t &a5)
|
||||
{
|
||||
if ( size < 4 )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return 0;
|
||||
}
|
||||
bytevec_t packed_buf;
|
||||
packed_buf.resize(size);
|
||||
uchar *packed = packed_buf.begin();
|
||||
qlseek(li, fpos);
|
||||
lread(li, packed, size);
|
||||
size_t usize = code0000.nBytesAboveA5 + code0000.nBytesBelowA5; // total data size
|
||||
enable_flags(ea, ea+usize, STT_CUR);
|
||||
|
||||
packed += sizeof(uint32); // skip initializers size
|
||||
size -= sizeof(uint32);
|
||||
|
||||
a5 = ea+code0000.nBytesBelowA5;
|
||||
ea_t cea;
|
||||
for ( int i=0; i < 3; i++ )
|
||||
{
|
||||
if ( size < 4 )
|
||||
goto BADDATA;
|
||||
int32 offset = swap32(*(uint32*)packed); // offset from A5
|
||||
packed += sizeof(uint32);
|
||||
size -= sizeof(uint32);
|
||||
cea = a5 + offset;
|
||||
if ( cea < ea )
|
||||
{
|
||||
// can happen when code 0 resource is not present (e.g. prc-tools GLib-type shared libs)
|
||||
if ( i != 0 )
|
||||
loader_failure("Error while decompressing data 0");
|
||||
cea = ea;
|
||||
a5 = ea-offset;
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
}
|
||||
if ( usize < cea-ea )
|
||||
usize = size_t(cea-ea);
|
||||
}
|
||||
|
||||
if ( a5 > ea + usize - 1 )
|
||||
{
|
||||
// allocate one extra byte for A5
|
||||
enable_flags(ea+usize, ea+usize+1, STT_CUR);
|
||||
usize++;
|
||||
}
|
||||
create_byte(a5,1);
|
||||
if ( a5 != ea )
|
||||
add_pgm_cmt("A5 register does not point to the start of the data segment\n"
|
||||
"The file should not be recompiled using Pila\n");
|
||||
set_name(a5,"A5BASE",SN_NOCHECK|SN_AUTO);
|
||||
set_cmt(a5,"A5 points here",0);
|
||||
// TODO: find undefined bytes and set them to zero
|
||||
// this is done by Palm OS loader and some programs depend on it
|
||||
|
||||
// process relocations
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a5 to a5
|
||||
// msg("Relocations: data to data\n");
|
||||
packed = apply_relocs(packed, size, a5, a5);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a5 to code
|
||||
// msg("Relocations: data to code1\n");
|
||||
packed = apply_relocs(packed, size, a5, code1ea, true);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
return usize;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// CodeWarrior A4 data layout:
|
||||
//
|
||||
// 0..3: 0x00000000
|
||||
// 4..7: size of "above A4" region
|
||||
// 8..11: size of "below A4" region
|
||||
// 12..N-1: compressed "below A4" data
|
||||
// N..N+3: size of "near above A4" region
|
||||
// N+4..O-1: compressed "near above A4" data
|
||||
// O..O+3: size of "far above A4" region
|
||||
// O+4..P-1: compressed "far above A4" data
|
||||
// then the relocations:
|
||||
// 1) A4 -> A4
|
||||
// 2) A4 -> A5
|
||||
// 3) A4 -> code0001
|
||||
// 4) A5 -> A4
|
||||
|
||||
static size_t unpack_data0001(linput_t *li, qoff64_t fpos, size_t size, ea_t ea, ea_t a5, ea_t code1ea, ea_t &a4)
|
||||
{
|
||||
if ( size < 3 * sizeof(uint32) )
|
||||
{
|
||||
BADDATA:
|
||||
warning("Bad packed data");
|
||||
return 0;
|
||||
}
|
||||
bytevec_t packed_buf;
|
||||
packed_buf.resize(size);
|
||||
uchar *packed = packed_buf.begin();
|
||||
qlseek(li, fpos);
|
||||
lread(li, packed, size);
|
||||
packed += sizeof(uint32); // skip the 0
|
||||
size -= sizeof(uint32);
|
||||
|
||||
int32 above = swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
int32 below = swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
size_t usize = above - below; // unpacked size
|
||||
if ( below & 1 )
|
||||
usize++;
|
||||
|
||||
ea_t cea = ea;
|
||||
a4 = ea-below;
|
||||
if ( below & 1 )
|
||||
a4++;
|
||||
enable_flags(ea, ea+usize, STT_CUR);
|
||||
create_byte(a4,1);
|
||||
set_name(a4,"A4BASE",SN_NOCHECK|SN_AUTO);
|
||||
set_cmt(a4,"A4 points here",0);
|
||||
|
||||
// unpack below a4
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
|
||||
// unpack near above a4
|
||||
if ( size < sizeof(int32) )
|
||||
goto BADDATA;
|
||||
cea = a4 + swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
|
||||
// unpack far above a4
|
||||
if ( size < sizeof(int32) )
|
||||
goto BADDATA;
|
||||
cea = a4 + swap32(*(int32*)packed);
|
||||
packed += sizeof(int32);
|
||||
size -= sizeof(uint32);
|
||||
packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin()));
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
|
||||
cea -= ea;
|
||||
if ( usize < cea )
|
||||
usize = (size_t)cea;
|
||||
|
||||
// process relocations
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a4 to a4
|
||||
// msg("Relocations: a4 to a4\n");
|
||||
packed = apply_relocs(packed, size, a4, a4);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a4 to a5
|
||||
// msg("Relocations: a4 to a5\n");
|
||||
packed = apply_relocs(packed, size, a4, a5);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a4 to code1
|
||||
// msg("Relocations: a4 to code1\n");
|
||||
packed = apply_relocs(packed, size, a4, code1ea, true);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
if ( size > 0 )
|
||||
{
|
||||
// a5 to a4
|
||||
// msg("Relocations: a5 to a4\n");
|
||||
packed = apply_relocs(packed, size, a5, a4);
|
||||
if ( packed == NULL )
|
||||
return 0;
|
||||
// packed = (uchar*)__Relocate__((Int8*)packed, 0, 0);
|
||||
}
|
||||
return usize;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void fix_jumptables(ea_t ea1, ea_t /*ea2*/, sel_t sel, ea_t a5, ea_t a4)
|
||||
{
|
||||
// msg("Fixing additional code segment at %08X\n",ea1);
|
||||
// from PalmOS_Startup.cpp
|
||||
/*
|
||||
struct SegmentHeader { // the structure of a segment header
|
||||
short jtsoffset; // A5 relative offset of this segments jump table (short version)
|
||||
short jtentries; // number of entries in this segments jump table
|
||||
int32 jtloffset; // A5 relative offset of this segments jump table (long version)
|
||||
int32 xrefoffset; // offset of xref data in this CODE resource
|
||||
char code[]; // the code
|
||||
};
|
||||
struct JumpTableEntry { // the structure of a jumptable entry
|
||||
short jumpinstruction; // instruction: jmp routine
|
||||
int32 jumpaddress; // absolute or relative address of rountine
|
||||
};*/
|
||||
|
||||
short jtsoffset = get_word(ea1);
|
||||
int32 jtloffset = get_dword(ea1+4);
|
||||
if ( jtsoffset != jtloffset )
|
||||
{
|
||||
// msg("Doesn't look like a CodeWarrior code segment\n");
|
||||
return;
|
||||
}
|
||||
// find the jumptable
|
||||
ea_t jt_start;
|
||||
if ( a4 != BADADDR && get_word(a4+jtloffset) == 0x4EF9 ) // jmp opcode
|
||||
{
|
||||
jt_start = a4+jtloffset;
|
||||
create_word(ea1,2);
|
||||
create_dword(ea1+4,4);
|
||||
op_offset(ea1, 0, REF_OFF16, BADADDR, a4);
|
||||
op_offset(ea1+4, 0, REF_OFF32, BADADDR, a4);
|
||||
}
|
||||
else if ( get_word(a5+jtloffset) == 0x4EF9 ) // jmp opcode
|
||||
{
|
||||
jt_start = a5+jtloffset;
|
||||
create_word(ea1,2);
|
||||
create_dword(ea1+4,4);
|
||||
op_offset(ea1, 0, REF_OFF16, BADADDR, a5);
|
||||
op_offset(ea1+4, 0, REF_OFF32, BADADDR, a5);
|
||||
}
|
||||
else
|
||||
{
|
||||
// msg("Could not find the jump table!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
create_word(ea1+2,2);
|
||||
create_dword(ea1+8,4);
|
||||
op_offset(ea1+8, 0, REF_OFF32, BADADDR, ea1);
|
||||
set_cmt(ea1, "Short jump table offset", 0);
|
||||
set_cmt(ea1+2, "Number of jump table entries", 0);
|
||||
set_cmt(ea1+4, "Long jump table offset", 0);
|
||||
set_cmt(ea1+8, "Offset to xref data", 0);
|
||||
|
||||
fixup_data_t fd(FIXUP_OFF32);
|
||||
fd.sel = sel;
|
||||
ea_t jt_addr=jt_start;
|
||||
short jtentries = get_word(ea1+2);
|
||||
while ( jtentries-- )
|
||||
{
|
||||
fd.off = get_dword(jt_addr+2);
|
||||
fd.set(jt_addr+2);
|
||||
// a little heuristic: does the jump point to code?
|
||||
if ( get_word(ea1+fd.off) == 0x4E56 // link a6,x
|
||||
|| get_word(ea1+fd.off) == 0x06AF ) // addi.l x, 4(sp)
|
||||
{
|
||||
auto_make_proc(ea1+fd.off);
|
||||
auto_make_proc(jt_addr);
|
||||
}
|
||||
jt_addr+=6;
|
||||
}
|
||||
// TODO: hide the table?
|
||||
// add_hidden_range(jt_start, jt_addr, "Jumptable for segment NNN", "", "", 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void doCodeOffset(ea_t ea, ea_t base)
|
||||
{
|
||||
create_dword(ea,4);
|
||||
uint32 off = get_dword(ea);
|
||||
op_offset(ea, 0, REF_OFF32, BADADDR, base, off&1);
|
||||
ea_t target = base+off;
|
||||
if ( off&1 )// last bit set: offset to thumb code
|
||||
{
|
||||
target &= (~1); // remove last bit
|
||||
// set_sreg_at_next_code(target,BADADDR,str2reg("T"),1);
|
||||
split_sreg_range(target,str2reg("T"),1,SR_auto,true);
|
||||
}
|
||||
auto_make_proc(target);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void fixArmCW(ea_t start_ea, ea_t end_ea)
|
||||
{
|
||||
// check for codewarrior relocation info
|
||||
/*
|
||||
typedef struct PnoHeaderType {
|
||||
00 UInt32 startupCode[8]; // changes based on the instruction count in startup code
|
||||
20 UInt32 pnoMain; // offset to ARMletMain routine
|
||||
24 UInt32 signature; // special PNO signature value
|
||||
28 UInt32 dataStart; // offset to start of initialized data
|
||||
2C UInt32 roDataStart; // offset to start of read-only initialized data
|
||||
30 UInt32 bssStart; // offset to start of uninitialized data
|
||||
34 UInt32 bssEnd; // offset to end of uninitialized data
|
||||
38 UInt32 codeRelocsStart; // offset to start of data-to-code relocation list
|
||||
3C UInt32 codeRelocsEnd; // offset to end of data-to-code relocation list
|
||||
40 UInt32 dataRelocsStart; // offset to start of data-to-data relocation list
|
||||
44 UInt32 dataRelocsEnd; // offset to end of data-to-data relocation list
|
||||
48 UInt32 altEntryCode[8]; // changes based on the instruction count in alternate entry code
|
||||
68
|
||||
} PnoHeaderType;
|
||||
*/
|
||||
const char *const comments[] =
|
||||
{
|
||||
"offset to ARMletMain routine",
|
||||
"special PNO signature value",
|
||||
"offset to start of initialized data",
|
||||
"offset to start of read-only initialized data",
|
||||
"offset to start of uninitialized data",
|
||||
"offset to end of uninitialized data",
|
||||
"offset to start of data-to-code relocation list",
|
||||
"offset to end of data-to-code relocation list",
|
||||
"offset to start of data-to-data relocation list",
|
||||
"offset to end of data-to-data relocation list",
|
||||
};
|
||||
|
||||
if ( end_ea-start_ea < 0x68 )
|
||||
return;
|
||||
for ( int i=0x20; i < 0x48; i+=4 )
|
||||
{
|
||||
create_dword(start_ea+i,4);
|
||||
if ( i == 0x24 )
|
||||
op_chr(start_ea+i, 0);
|
||||
else
|
||||
op_offset(start_ea+i, 0, REF_OFF32, BADADDR, start_ea);
|
||||
set_cmt(start_ea+i, comments[(i-0x20)/4],0);
|
||||
}
|
||||
auto_make_proc(start_ea);
|
||||
auto_make_proc(start_ea+0x48);
|
||||
doCodeOffset(start_ea+0x20,start_ea);
|
||||
|
||||
// do relocs
|
||||
ea_t cur = start_ea+get_dword(start_ea+0x38);
|
||||
ea_t end = start_ea+get_dword(start_ea+0x3C);
|
||||
for ( ; cur < end; cur+=4 )
|
||||
{
|
||||
create_dword(cur,4);
|
||||
op_offset(cur, 0, REF_OFF32, BADADDR, start_ea);
|
||||
doCodeOffset(start_ea+get_dword(cur), start_ea);
|
||||
}
|
||||
cur = start_ea+get_dword(start_ea+0x40);
|
||||
end = start_ea+get_dword(start_ea+0x44);
|
||||
for ( ; cur < end; cur+=4 )
|
||||
{
|
||||
create_dword(cur,4);
|
||||
op_offset(cur, 0, REF_OFF32, BADADDR, start_ea);
|
||||
ea_t o = start_ea+get_dword(cur);
|
||||
create_dword(o,4);
|
||||
op_offset(o, 0, REF_OFF32, BADADDR, start_ea);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// check for 'cdwr' signature
|
||||
bool isCWseg(linput_t *li, uint32 offset)
|
||||
{
|
||||
qlseek(li, offset + 0x24);
|
||||
uchar sig[4];
|
||||
qlread(li, sig, 4);
|
||||
return sig[0] == 'r'
|
||||
&& sig[1] == 'w'
|
||||
&& sig[2] == 'd'
|
||||
&& sig[3] == 'c';
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort neflags, const char * fileformatname)
|
||||
{
|
||||
int i;
|
||||
bool armCode = strcmp(fileformatname, PRC_ARM) == 0;
|
||||
bool manualMode = (neflags & NEF_MAN) != 0; // don't do any extra processing if set
|
||||
sel_t dgroup = BADSEL;
|
||||
|
||||
set_processor_type(armCode ? "ARM" : "68K", SETPROC_LOADER);
|
||||
set_target_assembler(armCode ? 0 : 2); // Generic ARM assembler/PalmPilot assembler Pila
|
||||
DatabaseHdrType h;
|
||||
lread(li,&h,sizeof(h));
|
||||
swap_prc(h);
|
||||
|
||||
qvector<ResourceMapEntry> re;
|
||||
re.resize(h.numRecords);
|
||||
lread(li, re.begin(), sizeof(ResourceMapEntry) * h.numRecords);
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
swap_resource_map_entry(re[i]);
|
||||
|
||||
code0000_t code0000 = { 0, 0 };
|
||||
if ( !armCode )
|
||||
{
|
||||
// sortResources(re, h.numRecords);
|
||||
// determine the bss size
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
if ( re[i].fcType == PILOT_RSC_CODE && re[i].id == 0 ) // code0000
|
||||
{
|
||||
qlseek(li, re[i].ulOffset);
|
||||
lread(li, &code0000, sizeof(code0000));
|
||||
swap_code0000(&code0000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ea_t a5 = BADADDR, a4 = BADADDR, code1ea = BADADDR;
|
||||
ea_t datastart = BADADDR;
|
||||
|
||||
// load the segments
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
// don't load known UI resources when asked not to
|
||||
if ( !(NEF_RSCS & neflags) && isKnownResource(re[i].fcType) )
|
||||
continue;
|
||||
// skip ARM chunks in 68K mode
|
||||
if ( !armCode && (re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL) )
|
||||
continue;
|
||||
|
||||
uint64 size;
|
||||
if ( i == (h.numRecords-1) )
|
||||
size = qlsize(li);
|
||||
else
|
||||
size = re[i+1].ulOffset;
|
||||
if ( size < re[i].ulOffset )
|
||||
loader_failure("Invalid file structure");
|
||||
size -= re[i].ulOffset;
|
||||
ea_t ea1 = (inf_get_max_ea() + 0xF) & ~0xF;
|
||||
ea_t ea2 = ea1 + size;
|
||||
|
||||
char segname[10];
|
||||
qsnprintf(segname, sizeof(segname), "%4.4s%04X", (char*)&re[i].fcType, re[i].id);
|
||||
const char *sclass = "RSC";
|
||||
|
||||
if ( armCode )
|
||||
{
|
||||
// load only ARM segments in ARM mode
|
||||
if ( re[i].fcType != PILOT_RSC_ARMC && re[i].fcType != PILOT_RSC_ARMCL )
|
||||
continue;
|
||||
|
||||
bool bCodeWarrior = isCWseg(li, re[i].ulOffset);
|
||||
|
||||
ea_t start_ea=ea1;
|
||||
file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE);
|
||||
int sel = i+1;
|
||||
if ( bCodeWarrior && !manualMode )
|
||||
{
|
||||
// load all sequential chunks as one segment
|
||||
while ( i < h.numRecords-1 && re[i].fcType == re[i+1].fcType && re[i].id + 1 == re[i+1].id && !isCWseg(li, re[i+1].ulOffset) )
|
||||
{
|
||||
i++;
|
||||
if ( i == (h.numRecords-1) )
|
||||
size = qlsize(li);
|
||||
else
|
||||
size = re[i+1].ulOffset;
|
||||
if ( size < re[i].ulOffset )
|
||||
loader_failure("Invalid file structure");
|
||||
size -= re[i].ulOffset;
|
||||
ea1 = ea2; // TODO: check if pnoloader.c does alignment
|
||||
ea2 = ea1 + size;
|
||||
file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE);
|
||||
}
|
||||
}
|
||||
set_selector(sel, start_ea >> 4);
|
||||
if ( !add_segm(sel, start_ea, ea2, segname, CLASS_CODE, ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
|
||||
// set DS for the segment to itself
|
||||
set_default_sreg_value(get_segm_by_sel(sel), str2reg("DS"), sel);
|
||||
if ( bCodeWarrior )
|
||||
fixArmCW(start_ea, ea2);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( re[i].fcType == PILOT_RSC_CODE )
|
||||
{
|
||||
if ( re[i].id == 0 && !manualMode )
|
||||
continue; // skip code0000 resource
|
||||
sclass = CLASS_CODE;
|
||||
if ( re[i].id == 1 )
|
||||
{
|
||||
inf_set_start_cs(i + 1);
|
||||
inf_set_start_ip(0);
|
||||
code1ea = ea1;
|
||||
}
|
||||
}
|
||||
else if ( re[i].fcType == PILOT_RSC_LIBR || re[i].fcType == PILOT_RSC_GLIB )
|
||||
{
|
||||
sclass = CLASS_CODE;
|
||||
if ( re[i].id == 0 )
|
||||
{
|
||||
inf_set_start_cs(i + 1);
|
||||
inf_set_start_ip(0);
|
||||
code1ea = ea1;
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to decompress stuff
|
||||
if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 0 )
|
||||
{
|
||||
sclass = CLASS_DATA;
|
||||
dgroup = i + 1;
|
||||
size_t usize = unpack_data0000(li, re[i].ulOffset, size, ea1, code0000, code1ea, a5);
|
||||
ea2 = ea1 + usize;
|
||||
datastart = ea1;
|
||||
}
|
||||
else if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 1 && !manualMode )
|
||||
{
|
||||
sclass = CLASS_DATA;
|
||||
size_t usize = unpack_data0001(li, re[i].ulOffset, size, ea1, a5, code1ea, a4);
|
||||
ea2 = ea1 + usize;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise just load it as-is
|
||||
file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE);
|
||||
}
|
||||
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = ea1;
|
||||
s.end_ea = ea2;
|
||||
s.sel = i+1;
|
||||
s.bitness = 1; // 32bit
|
||||
set_selector(i+1, ea1 >> 4);
|
||||
if ( !add_segm_ex(&s, segname, sclass, ADDSEG_FILLGAP|ADDSEG_OR_DIE|ADDSEG_SPARSE) )
|
||||
loader_failure();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !manualMode && !armCode )
|
||||
{
|
||||
// check if first dword is 1; if so, skip it
|
||||
if ( get_dword(code1ea) == 1 )
|
||||
{
|
||||
// codewarrior startup
|
||||
static const uchar pattern[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x01, // dc.l 1
|
||||
0x48, 0x7A, 0x00, 0x04, // pea $A
|
||||
0x06, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, // addi.l #(__Startup__-$A),(sp)
|
||||
0x4E, 0x75, // rts
|
||||
};
|
||||
if ( equal_bytes(code1ea, pattern, SKIP_FF_MASK, sizeof(pattern), true) )
|
||||
{
|
||||
plan_to_apply_idasgn("cwpalm.sig");
|
||||
}
|
||||
create_dword(code1ea, 4);
|
||||
inf_set_start_ip(4);
|
||||
}
|
||||
// is main code segment GLib?
|
||||
if ( inf_get_start_cs() > 0
|
||||
&& re[int(inf_get_start_cs()-1)].fcType == PILOT_RSC_GLIB
|
||||
&& a4 == BADADDR
|
||||
&& datastart != BADADDR )
|
||||
{
|
||||
// GLib's a4 points at the start of data segment
|
||||
a4 = datastart;
|
||||
create_byte(a4, 1);
|
||||
set_name(a4, "A4BASE", SN_NOCHECK|SN_AUTO);
|
||||
set_cmt(a4, "A4 points here", 0);
|
||||
}
|
||||
// check for CodeWarrior's jumptables in additional code segments and fix them up
|
||||
for ( i=0; i < h.numRecords; i++ )
|
||||
{
|
||||
if ( re[i].fcType == PILOT_RSC_CODE && re[i].id > 1 )
|
||||
{
|
||||
segment_t *seg = get_segm_by_sel(i+1);
|
||||
if ( seg != NULL )
|
||||
fix_jumptables(seg->start_ea, seg->end_ea, i+1, a5, a4);
|
||||
}
|
||||
}
|
||||
// TODO: handle prc-tools and multilink's 'rloc' segments
|
||||
}
|
||||
|
||||
if ( dgroup != BADSEL )
|
||||
set_default_dataseg(dgroup); // input: selector
|
||||
describe_all(h);
|
||||
exec_system_script("pilot.idc");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// it is impossible to use ph.id,
|
||||
// the processor module is not loaded yet
|
||||
inline bool is_arm_specified(void)
|
||||
{
|
||||
return strnieq(inf_get_procname().c_str(), "ARM", 3);
|
||||
}
|
||||
|
||||
inline bool is_68k_specified(void)
|
||||
{
|
||||
char pname[IDAINFO_PROCNAME_SIZE];
|
||||
inf_get_procname(pname, sizeof(pname));
|
||||
return strnieq(pname, "68K", 3)
|
||||
|| strnieq(pname, "68000", 5)
|
||||
|| strnieq(pname, "68010", 5)
|
||||
|| strnieq(pname, "68020", 5)
|
||||
|| strnieq(pname, "68030", 5)
|
||||
|| strnieq(pname, "68040", 5)
|
||||
|| strnieq(pname, "68330", 5)
|
||||
|| strnieq(pname, "68882", 5)
|
||||
|| strnieq(pname, "68851", 5)
|
||||
|| strnieq(pname, "ColdFire", 8);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
static int n = 0;
|
||||
int k = is_prc_file(li);
|
||||
if ( k == 0 )
|
||||
return 0;
|
||||
int ftype = 0;
|
||||
if ( n == 1 )
|
||||
{
|
||||
if ( k == 2 ) // has ARM segments?
|
||||
{
|
||||
*fileformatname = PRC_ARM;
|
||||
*processor = "ARM";
|
||||
ftype = f_PRC;
|
||||
if ( is_arm_specified() )
|
||||
ftype |= ACCEPT_FIRST;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
n++;
|
||||
*fileformatname = PRC_68K;
|
||||
*processor = "68K";
|
||||
ftype = f_PRC|ACCEPT_CONTINUE;
|
||||
if ( is_68k_specified() )
|
||||
ftype |= ACCEPT_FIRST;
|
||||
}
|
||||
return ftype;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
loader_t LDSC =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
0, // loader flags
|
||||
//
|
||||
// check input file format. if recognized, then return 1
|
||||
// and fill 'fileformatname'.
|
||||
// otherwise return 0
|
||||
//
|
||||
accept_file,
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
load_file,
|
||||
//
|
||||
// create output file from the database.
|
||||
// this function may be absent.
|
||||
//
|
||||
NULL,
|
||||
// take care of a moved segment (fix up relocations, for example)
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
148
idasdk76/ldr/pilot/pilot.hpp
Normal file
148
idasdk76/ldr/pilot/pilot.hpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PILOT_H
|
||||
#define __PILOT_H
|
||||
#pragma pack(push, 1)
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define PRC_68K "PalmPilot program file (68K)"
|
||||
#define PRC_ARM "PalmPilot program file (ARM)"
|
||||
|
||||
// Regular resources:
|
||||
|
||||
#define PILOT_RSC_CODE 0x65646F63L // "code\0\0\0\1" program code
|
||||
#define PILOT_RSC_PREF 0x66657270L // "pref\0\0\0\0" preferences (not used yet)
|
||||
#define PILOT_RSC_DATA 0x61746164L // "data\0\0\0\0" image of global data
|
||||
#define PILOT_RSC_LIBR 0x7262696CL // "libr" SysLib-type shared library code
|
||||
#define PILOT_RSC_GLIB 0x62694C47L // "GLib" PRC-Tools GLib-type shared library code
|
||||
#define PILOT_RSC_RLOC 0x636F6C72L // "rloc" PRC-Tools and Multilink relocations
|
||||
#define PILOT_RSC_ARMC 0x434D5241L // "ARMC" ARM native code
|
||||
#define PILOT_RSC_ARMCL 0x636D7261L // "armc" ARM native code
|
||||
|
||||
// UI resources:
|
||||
|
||||
#define PILOT_RSC_MBAR 0x5241424DL // "MBAR" Menu bar
|
||||
#define PILOT_RSC_MENU 0x554E454DL // "MENU" Menu options
|
||||
#define PILOT_RSC_ICON 0x4E494174L // "tAIN" Application icon name
|
||||
#define PILOT_RSC_AIB 0x42494174L // "tAIB" Application icon bitmap
|
||||
#define PILOT_RSC_AIS 0x53494174L // "tAIS" Application information string
|
||||
#define PILOT_RSC_ALERT 0x746C6154L // "Talt" Alert
|
||||
#define PILOT_RSC_BITMAP 0x706D6254L // "Tbmp" Bitmap
|
||||
#define PILOT_RSC_BUTTON 0x4E544274L // "tBTN" Button
|
||||
#define PILOT_RSC_CHECK 0x58424374L // "tCBX" Check box
|
||||
#define PILOT_RSC_FBM 0x4D424674L // "tFBM" Form bitmap
|
||||
#define PILOT_RSC_FIELD 0x444C4674L // "tFLD" Field
|
||||
#define PILOT_RSC_FORM 0x4D524674L // "tFRM" Form
|
||||
#define PILOT_RSC_GADGET 0x54444774L // "tGDT" Gadget
|
||||
#define PILOT_RSC_GRAFF 0x49534774L // "tGSI" Graffiti Shift
|
||||
#define PILOT_RSC_LABEL 0x4C424C74L // "tLBL" Label
|
||||
#define PILOT_RSC_LIST 0x54534C74L // "tLST" List box
|
||||
#define PILOT_RSC_PUSH 0x4E425074L // "tPBN" Push button
|
||||
#define PILOT_RSC_POPUPL 0x4C555074L // "tPUL" Popup list
|
||||
#define PILOT_RSC_POPUPT 0x54555074L // "tPUT" Popup trigger
|
||||
#define PILOT_RSC_REPEAT 0x50455274L // "tREP" Repeating control
|
||||
#define PILOT_RSC_SELECT 0x544C5374L // "tSLT" Selector trigger
|
||||
#define PILOT_RSC_STRING 0x52545374L // "tSTR" String
|
||||
#define PILOT_RSC_TABLE 0x4C425474L // "tTBL" Table
|
||||
#define PILOT_RSC_TITLE 0x4C545474L // "tTTL" Title
|
||||
#define PILOT_RSC_VER 0x72657674L // "tver" Version number string
|
||||
|
||||
|
||||
typedef uchar Byte;
|
||||
typedef ushort Word;
|
||||
typedef uint32 DWord;
|
||||
typedef DWord LocalID;
|
||||
|
||||
//
|
||||
// Header of PRC file:
|
||||
//
|
||||
|
||||
struct DatabaseHdrType
|
||||
{
|
||||
Byte name[32]; // name of database
|
||||
#define PILOT_CREATOR_PILA 0x616C6950L // "Pila"
|
||||
Word attributes; // database attributes
|
||||
#define dmHdrAttrResDB 0x0001 // Resource database
|
||||
#define dmHdrAttrReadOnly 0x0002 // Read Only database
|
||||
#define dmHdrAttrAppInfoDirty 0x0004 // Set if Application Info block is dirty
|
||||
// Optionally supported by an App's conduit
|
||||
#define dmHdrAttrBackup 0x0008 // Set if database should be backed up to PC if
|
||||
// no app-specific synchronization conduit has
|
||||
// been supplied.
|
||||
#define dmHdrAttrOpen 0x8000 // Database not closed properly
|
||||
Word version; // version of database
|
||||
DWord creationDate; // creation date of database
|
||||
DWord modificationDate; // latest modification date
|
||||
DWord lastBackupDate; // latest backup date
|
||||
DWord modificationNumber; // modification number of database
|
||||
LocalID appInfoID; // application specific info
|
||||
LocalID sortInfoID; // app specific sorting info
|
||||
DWord type; // database type
|
||||
#define PILOT_TYPE_APPL 0x6C707061L // "appl"
|
||||
DWord id; // program id
|
||||
DWord uniqueIDSeed; // used to generate unique IDs.
|
||||
// Note that only the low order
|
||||
// 3 bytes of this is used (in
|
||||
// RecordEntryType.uniqueID).
|
||||
// We are keeping 4 bytes for
|
||||
// alignment purposes.
|
||||
LocalID nextRecordListID; // local chunkID of next list
|
||||
Word numRecords; // number of records in this list
|
||||
};
|
||||
|
||||
//
|
||||
// Each resource has the following entry:
|
||||
//
|
||||
struct ResourceMapEntry
|
||||
{
|
||||
uint32 fcType;
|
||||
ushort id;
|
||||
uint32 ulOffset;
|
||||
};
|
||||
|
||||
|
||||
// Pilot bitmap format (also format of icon)
|
||||
struct pilot_bitmap_t
|
||||
{
|
||||
ushort cx;
|
||||
ushort cy;
|
||||
ushort cbRow;
|
||||
ushort ff;
|
||||
ushort ausUnk[4];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* code0000[long 0] nBytesAboveA5
|
||||
* code0000[long 1] nBytesBelowA5
|
||||
*/
|
||||
struct code0000_t
|
||||
{
|
||||
uint32 nBytesAboveA5;
|
||||
uint32 nBytesBelowA5;
|
||||
};
|
||||
|
||||
// pref0000
|
||||
|
||||
struct pref0000_t
|
||||
{
|
||||
ushort flags;
|
||||
#define sysAppLaunchFlagNewThread 0x0001
|
||||
#define sysAppLaunchFlagNewStack 0x0002
|
||||
#define sysAppLaunchFlagNewGlobals 0x0004
|
||||
#define sysAppLaunchFlagUIApp 0x0008
|
||||
#define sysAppLaunchFlagSubCall 0x0010
|
||||
uint32 stack_size;
|
||||
uint32 heap_size;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif // __PILOT_H
|
||||
216
idasdk76/ldr/pilot/pilot.idc
Normal file
216
idasdk76/ldr/pilot/pilot.idc
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// This file is executed when a PalmPilot program is loaded.
|
||||
// You may customize it as you wish.
|
||||
//
|
||||
// TODO:
|
||||
// - decompilation of various resource types
|
||||
// (we don't have any information on the formats)
|
||||
//
|
||||
|
||||
#include <idc.idc>
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Process each resource and make some routine tasks
|
||||
//
|
||||
static process_segments()
|
||||
{
|
||||
auto ea,segname,prefix;
|
||||
|
||||
for ( ea=get_first_seg(); ea != BADADDR; ea=get_next_seg(ea) )
|
||||
{
|
||||
segname = get_segm_name(ea);
|
||||
prefix = substr(segname,0,4);
|
||||
if ( segname == "data0000" )
|
||||
{
|
||||
if ( get_wide_dword(ea) == 0xFFFFFFFF )
|
||||
{
|
||||
create_dword(ea);
|
||||
set_cmt(ea,"Loader stores SysAppInfoPtr here", 0);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "TRAP" )
|
||||
{
|
||||
create_word(ea);
|
||||
op_hex(ea,0);
|
||||
set_cmt(ea,"System trap function code", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "tSTR" )
|
||||
{
|
||||
create_strlit(ea,get_segm_end(ea));
|
||||
set_cmt(ea,"String resource", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "tver" )
|
||||
{
|
||||
create_strlit(ea,get_segm_end(ea));
|
||||
set_cmt(ea,"Version number string", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "tAIN" )
|
||||
{
|
||||
create_strlit(ea,get_segm_end(ea));
|
||||
set_cmt(ea,"Application icon name", 0);
|
||||
continue;
|
||||
}
|
||||
if ( prefix == "pref" )
|
||||
{
|
||||
auto flags,cmt;
|
||||
flags = get_wide_word(ea);
|
||||
create_word(ea); op_hex(ea,0); set_name(ea,"flags");
|
||||
#define sysAppLaunchFlagNewThread 0x0001
|
||||
#define sysAppLaunchFlagNewStack 0x0002
|
||||
#define sysAppLaunchFlagNewGlobals 0x0004
|
||||
#define sysAppLaunchFlagUIApp 0x0008
|
||||
#define sysAppLaunchFlagSubCall 0x0010
|
||||
cmt = "";
|
||||
if ( flags & sysAppLaunchFlagNewThread ) cmt = cmt + "sysAppLaunchFlagNewThread\n";
|
||||
if ( flags & sysAppLaunchFlagNewStack ) cmt = cmt + "sysAppLaunchFlagNewStack\n";
|
||||
if ( flags & sysAppLaunchFlagNewGlobals) cmt = cmt + "sysAppLaunchFlagNewGlobals\n";
|
||||
if ( flags & sysAppLaunchFlagUIApp ) cmt = cmt + "sysAppLaunchFlagUIApp\n";
|
||||
if ( flags & sysAppLaunchFlagSubCall ) cmt = cmt + "sysAppLaunchFlagSubCall";
|
||||
set_cmt(ea,cmt, 0);
|
||||
ea = ea + 2;
|
||||
create_dword(ea); op_hex(ea,0); set_name(ea,"stack_size");
|
||||
ea = ea + 4;
|
||||
create_dword(ea); op_hex(ea,0); set_name(ea,"heap_size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Create a enumeration with system action codes
|
||||
//
|
||||
static make_actions()
|
||||
{
|
||||
auto id;
|
||||
id = add_enum(-1,"SysAppLaunchCmd",FF_0NUMD);
|
||||
if ( id != -1 )
|
||||
{
|
||||
set_enum_cmt(id,"Action codes",0);
|
||||
add_enum_member(id, "sysAppLaunchCmdNormalLaunch", 0, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdFind", 1, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdGoTo", 2, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSyncNotify", 3, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdTimeChange", 4, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSystemReset", 5, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdAlarmTriggered", 6, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdDisplayAlarm", 7, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdCountryChange", 8, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSyncRequest", 9, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSaveData", 10, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdInitDatabase", 11, -1);
|
||||
add_enum_member(id, "sysAppLaunchCmdSyncCallApplication", 12, -1);
|
||||
set_enum_member_cmt(get_enum_member(id, 0, 0, -1), "Normal Launch", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 1, 0, -1), "Find string", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 2, 0, -1), "Launch and go to a particular record", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 3, 0, -1),
|
||||
"Sent to apps whose databases changed\n"
|
||||
"during HotSync after the sync has\n"
|
||||
"been completed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 4, 0, -1), "The system time has changed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 5, 0, -1), "Sent after System hard resets", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 6, 0, -1), "Schedule next alarm", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 7, 0, -1), "Display given alarm dialog", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 8, 0, -1), "The country has changed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 9, 0, -1), "The \"HotSync\" button was pressed", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 10, 0, -1),
|
||||
"Sent to running app before\n"
|
||||
"sysAppLaunchCmdFind or other\n"
|
||||
"action codes that will cause data\n"
|
||||
"searches or manipulation", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 11, 0, -1),
|
||||
"Initialize a database; sent by\n"
|
||||
"DesktopLink server to the app whose\n"
|
||||
"creator ID matches that of the database\n"
|
||||
"created in response to the \"create db\" request", 1);
|
||||
set_enum_member_cmt(get_enum_member(id, 12, 0, -1),
|
||||
"Used by DesktopLink Server command\n"
|
||||
"\"call application\"", 1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Create a enumeration with event codes
|
||||
//
|
||||
static make_events()
|
||||
{
|
||||
auto id;
|
||||
id = add_enum(-1,"events",FF_0NUMD);
|
||||
if ( id != -1 )
|
||||
{
|
||||
set_enum_cmt(id,"Event codes",0);
|
||||
add_enum_member(id, "nilEvent", 0, -1);
|
||||
add_enum_member(id,"penDownEvent", 1, -1);
|
||||
add_enum_member(id,"penUpEvent", 2, -1);
|
||||
add_enum_member(id,"penMoveEvent", 3, -1);
|
||||
add_enum_member(id,"keyDownEvent", 4, -1);
|
||||
add_enum_member(id,"winEnterEvent", 5, -1);
|
||||
add_enum_member(id,"winExitEvent", 6, -1);
|
||||
add_enum_member(id,"ctlEnterEvent", 7, -1);
|
||||
add_enum_member(id,"ctlExitEvent", 8, -1);
|
||||
add_enum_member(id,"ctlSelectEvent", 9, -1);
|
||||
add_enum_member(id,"ctlRepeatEvent", 10, -1);
|
||||
add_enum_member(id,"lstEnterEvent", 11, -1);
|
||||
add_enum_member(id,"lstSelectEvent", 12, -1);
|
||||
add_enum_member(id,"lstExitEvent", 13, -1);
|
||||
add_enum_member(id,"popSelectEvent", 14, -1);
|
||||
add_enum_member(id,"fldEnterEvent", 15, -1);
|
||||
add_enum_member(id,"fldHeightChangedEvent", 16, -1);
|
||||
add_enum_member(id,"fldChangedEvent", 17, -1);
|
||||
add_enum_member(id,"tblEnterEvent", 18, -1);
|
||||
add_enum_member(id,"tblSelectEvent", 19, -1);
|
||||
add_enum_member(id,"daySelectEvent", 20, -1);
|
||||
add_enum_member(id,"menuEvent", 21, -1);
|
||||
add_enum_member(id,"appStopEvent", 22, -1);
|
||||
add_enum_member(id,"frmLoadEvent", 23, -1);
|
||||
add_enum_member(id,"frmOpenEvent", 24, -1);
|
||||
add_enum_member(id,"frmGotoEvent", 25, -1);
|
||||
add_enum_member(id,"frmUpdateEvent", 26, -1);
|
||||
add_enum_member(id,"frmSaveEvent", 27, -1);
|
||||
add_enum_member(id,"frmCloseEvent", 28, -1);
|
||||
add_enum_member(id,"tblExitEvent", 29, -1);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static main()
|
||||
{
|
||||
process_segments();
|
||||
make_actions();
|
||||
make_events();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#ifdef __undefined_symbol__
|
||||
// WE DO NOT USE IDC HOTKEYS, JUST SIMPLE KEYBOARD MACROS
|
||||
// (see IDA.CFG, macro Alt-5 for mc68k)
|
||||
//-----------------------------------------------------------------------
|
||||
//
|
||||
// Register Ctrl-R as a hotkey for "make offset from A5" command
|
||||
// (not used, simple keyboard macro is used instead, see IDA.CFG)
|
||||
//
|
||||
// There is another (manual) way to convert an operand to an offset:
|
||||
// - press Ctrl-R
|
||||
// - enter "A5BASE"
|
||||
// - press Enter
|
||||
//
|
||||
static setup_pilot()
|
||||
{
|
||||
auto h0,h1;
|
||||
h0 = "Alt-1";
|
||||
h1 = "Alt-2";
|
||||
add_idc_hotkey(h0,"a5offset0");
|
||||
add_idc_hotkey(h1,"a5offset1");
|
||||
msg("Use %s to convert the first operand to an offset from A5\n",h0);
|
||||
msg("Use %s to convert the second operand to an offset from A5\n",h1);
|
||||
}
|
||||
|
||||
static a5offset0(void) { op_plain_offset(get_screen_ea(),0,get_name_ea_simple("A5BASE")); }
|
||||
static a5offset1(void) { op_plain_offset(get_screen_ea(),1,get_name_ea_simple("A5BASE")); }
|
||||
|
||||
#endif // 0
|
||||
115
idasdk76/ldr/qnx/lmf.h
Normal file
115
idasdk76/ldr/qnx/lmf.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* lmf.h Load Module Format
|
||||
*
|
||||
* Copyright by QNX Software Systems Limited 1990-1993. All rights reserved.
|
||||
*/
|
||||
#ifndef __LMF_H_INCLUDED
|
||||
#define __LMF_H_INCLUDED
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct _lmf_header { /* This preceeds each record defined below */
|
||||
char rec_type,
|
||||
zero1;
|
||||
short unsigned data_nbytes,
|
||||
spare;
|
||||
} ;
|
||||
|
||||
|
||||
struct _lmf_definition { /* Must be first record in load file */
|
||||
short unsigned version_no,
|
||||
cflags,
|
||||
cpu,
|
||||
fpu,
|
||||
code_index,
|
||||
stack_index,
|
||||
heap_index,
|
||||
argv_index,
|
||||
zero1[4];
|
||||
int32 code_offset,
|
||||
stack_nbytes,
|
||||
heap_nbytes,
|
||||
flat_offset,
|
||||
unmapped_size,
|
||||
zero2;
|
||||
/* Variable length field of n longs starts here */
|
||||
} ;
|
||||
|
||||
|
||||
struct _lmf_data { /* Code or data record to load into memory */
|
||||
short segment_index;
|
||||
uint32 offset;
|
||||
/* Variable length field of n bytes starts here */
|
||||
} ;
|
||||
|
||||
|
||||
struct _lmf_seg_fixup { /* Segment fixup record */
|
||||
struct fixups {
|
||||
short unsigned fixup_seg_index;
|
||||
int32 fixup_offset;
|
||||
} data[1]; /* May be n of these */
|
||||
} ;
|
||||
|
||||
|
||||
struct _lmf_linear_fixup { /* Segment fixup record */
|
||||
short unsigned fixup_seg_index;
|
||||
int32 fixup_offset[1];
|
||||
} ;
|
||||
|
||||
|
||||
struct _lmf_eof {
|
||||
char zero[6];
|
||||
} ;
|
||||
|
||||
|
||||
struct _lmf_resource {
|
||||
short unsigned resource_type; /* 0 - usage messages */
|
||||
short unsigned zero[3];
|
||||
} ;
|
||||
|
||||
|
||||
/*
|
||||
* Record types
|
||||
*/
|
||||
|
||||
#define _LMF_DEFINITION_REC 0
|
||||
#define _LMF_COMMENT_REC 1
|
||||
#define _LMF_DATA_REC 2
|
||||
#define _LMF_FIXUP_SEG_REC 3
|
||||
#define _LMF_FIXUP_80X87_REC 4
|
||||
#define _LMF_EOF_REC 5
|
||||
#define _LMF_RESOURCE_REC 6
|
||||
#define _LMF_ENDDATA_REC 7
|
||||
#define _LMF_FIXUP_LINEAR_REC 8
|
||||
#define _LMF_PHRESOURCE 9 // A widget resource for photon apps
|
||||
|
||||
|
||||
/*
|
||||
* Bit defitions for lh_code_flags
|
||||
*/
|
||||
|
||||
#define _PCF_LONG_LIVED 0x0001
|
||||
#define _PCF_32BIT 0x0002
|
||||
#define _PCF_PRIVMASK 0x000c /* Two bits */
|
||||
#define _PCF_FLAT 0x0010
|
||||
#define _PCF_NOSHARE 0x0020
|
||||
|
||||
/*
|
||||
* The top 4 bits of the segment sizes
|
||||
*/
|
||||
|
||||
#define _LMF_CODE 0x2
|
||||
|
||||
|
||||
#define MIN_SEGMENTS 1 // usually 2 or 4
|
||||
#define MAX_SEGMENTS 4
|
||||
|
||||
|
||||
struct ex_header {
|
||||
struct _lmf_header lmf_header;
|
||||
struct _lmf_definition lmf_definition;
|
||||
uint32 segsizes[MAX_SEGMENTS];
|
||||
};
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
13
idasdk76/ldr/qnx/makefile
Normal file
13
idasdk76/ldr/qnx/makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
PROC=qnx
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)qnx$(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 ../idaldr.h lmf.h qnx.cpp
|
||||
372
idasdk76/ldr/qnx/qnx.cpp
Normal file
372
idasdk76/ldr/qnx/qnx.cpp
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
IDA LOADER for QNX 16/32 bit executables
|
||||
(c) Zhengxi Ltd., 1998.
|
||||
|
||||
start: 25.07.98
|
||||
end: 26.07.98
|
||||
|
||||
changed:
|
||||
28.07.98 Yury Haron
|
||||
09.08.98 Denis Petrov
|
||||
10.08.98 YH - patch to new sdk format
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "lmf.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *)
|
||||
{
|
||||
ex_header ex; // lmf header
|
||||
uint32 n_segments; // segment count
|
||||
|
||||
if ( qlread(li, &ex, sizeof(ex)) != sizeof(ex) )
|
||||
return 0;
|
||||
if ( 0 != ex.lmf_header.rec_type )
|
||||
return 0;
|
||||
if ( 0 != ex.lmf_header.zero1 )
|
||||
return 0;
|
||||
// if ( 0x38 != ex.lmf_header.data_nbytes ) return 0;
|
||||
if ( 0 != ex.lmf_header.spare )
|
||||
return 0;
|
||||
if ( 386 != ex.lmf_definition.cpu
|
||||
&& 286 != ex.lmf_definition.cpu )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
n_segments = (ex.lmf_header.data_nbytes - sizeof(_lmf_definition))
|
||||
/ sizeof (uint32);
|
||||
|
||||
if ( (MIN_SEGMENTS > n_segments) || (n_segments > MAX_SEGMENTS) )
|
||||
return 0;
|
||||
|
||||
_lmf_data lmf_data;
|
||||
lmf_data.segment_index = -1;
|
||||
|
||||
uint64 file_size = qlsize(li);
|
||||
|
||||
for ( uint32 at = sizeof(ex.lmf_header) + ex.lmf_header.data_nbytes;
|
||||
lmf_data.segment_index != _LMF_EOF_REC;
|
||||
)
|
||||
{
|
||||
qlseek(li, at, 0);
|
||||
if ( sizeof(_lmf_data) != qlread(li, &lmf_data, sizeof(_lmf_data) ) )
|
||||
return 0;
|
||||
|
||||
switch ( lmf_data.segment_index )
|
||||
{
|
||||
case _LMF_DEFINITION_REC:
|
||||
return 0;
|
||||
case _LMF_COMMENT_REC:
|
||||
break;
|
||||
case _LMF_DATA_REC:
|
||||
break;
|
||||
case _LMF_FIXUP_SEG_REC:
|
||||
break;
|
||||
case _LMF_FIXUP_80X87_REC:
|
||||
break;
|
||||
case _LMF_EOF_REC:
|
||||
if ( lmf_data.offset != sizeof(_lmf_eof) )
|
||||
return 0;
|
||||
break;
|
||||
case _LMF_RESOURCE_REC:
|
||||
break;
|
||||
case _LMF_ENDDATA_REC:
|
||||
if ( lmf_data.offset != 6 /*sizeof(???)*/ )
|
||||
return 0;
|
||||
break;
|
||||
case _LMF_FIXUP_LINEAR_REC:
|
||||
break;
|
||||
case _LMF_PHRESOURCE:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if ( sizeof(lmf_data) + uint64(lmf_data.offset) > file_size )
|
||||
return 0;
|
||||
at += sizeof(lmf_data) + lmf_data.offset;
|
||||
}
|
||||
|
||||
fileformatname->sprnt("QNX %d-executable",
|
||||
(_PCF_32BIT & ex.lmf_definition.cflags)
|
||||
? 32
|
||||
: 16);
|
||||
*processor = "metapc";
|
||||
return f_LOADER;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
//#define _CODE 0
|
||||
//#define _DATA 1
|
||||
//#define _BSS 2
|
||||
//#define _STACK 3
|
||||
//#define MAXSEG 2
|
||||
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
ex_header ex; // lmf header
|
||||
uint32 n_segments; // segment count
|
||||
uint32 nseg; // watcom 10.6 not working properly without this!
|
||||
qoff64_t filelen = qlsize(li);
|
||||
|
||||
set_processor_type("metapc", SETPROC_LOADER);
|
||||
|
||||
qlseek(li, 0);
|
||||
lread(li, &ex, sizeof(ex));
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 minea,topea;
|
||||
} perseg[MAX_SEGMENTS];
|
||||
|
||||
n_segments = (ex.lmf_header.data_nbytes - sizeof(_lmf_definition))
|
||||
/ sizeof (uint32);
|
||||
if ( n_segments > MAX_SEGMENTS )
|
||||
{
|
||||
msg("QNX: a lot of segments %u\n", n_segments);
|
||||
loader_failure("Bad file header format");
|
||||
}
|
||||
|
||||
for ( nseg = 0; nseg < n_segments; nseg++ )
|
||||
{
|
||||
if ( nseg == 0 )
|
||||
perseg[nseg].minea = ex.lmf_definition.flat_offset;
|
||||
else
|
||||
perseg[nseg].minea = (perseg[nseg-1].topea + 0x0FFF) & ~0x0FFF;
|
||||
perseg[nseg].topea = perseg[nseg].minea + (ex.segsizes[nseg] & 0x0FFFFFFF);
|
||||
|
||||
if ( perseg[nseg].minea > perseg[nseg].topea )
|
||||
loader_failure("Bad file header format");
|
||||
}
|
||||
|
||||
uint32 ring = (_PCF_PRIVMASK &ex.lmf_definition.cflags)>>2;
|
||||
|
||||
// uint32 myselector = 0x04 + ring;
|
||||
|
||||
// LDT selectors in order.
|
||||
#define LDT_SELECTOR(nseg) (((nseg)<<3)+0x04+ring)
|
||||
#define ISFLAT (_PCF_FLAT &ex.lmf_definition.cflags)
|
||||
|
||||
inf_set_baseaddr(0);
|
||||
if ( ISFLAT )
|
||||
{
|
||||
inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT);
|
||||
// inf.s_prefflag &= ~PREF_SEGADR;
|
||||
// inf.nametype = NM_EA4;
|
||||
}
|
||||
|
||||
inf_set_start_ip(ex.lmf_definition.code_offset);
|
||||
if ( ex.lmf_definition.code_index >= n_segments )
|
||||
loader_failure("Corrupted file");
|
||||
|
||||
if ( ISFLAT )
|
||||
inf_set_start_ip(inf_get_start_ip() + perseg[ex.lmf_definition.code_index].minea);
|
||||
inf_set_start_cs(LDT_SELECTOR(ex.lmf_definition.code_index));
|
||||
|
||||
_lmf_data lmf_data, lmf_data2;
|
||||
lmf_data.segment_index = -1;
|
||||
|
||||
for ( uint32 at = sizeof(ex.lmf_header)+ex.lmf_header.data_nbytes;
|
||||
lmf_data.segment_index != _LMF_EOF_REC;
|
||||
at += sizeof(lmf_data) + lmf_data.offset )
|
||||
{
|
||||
if ( qlseek(li, at ) != at )
|
||||
loader_failure("Corrupted file");
|
||||
lread(li, &lmf_data, sizeof(_lmf_data));
|
||||
switch ( lmf_data.segment_index )
|
||||
{
|
||||
|
||||
case _LMF_DEFINITION_REC:
|
||||
break;
|
||||
|
||||
case _LMF_COMMENT_REC:
|
||||
break;
|
||||
|
||||
case _LMF_DATA_REC:
|
||||
{
|
||||
lread(li, &lmf_data2, sizeof(_lmf_data));
|
||||
if ( lmf_data2.segment_index >= n_segments )
|
||||
loader_failure("Corrupted file");
|
||||
uint32 body_offset = perseg[lmf_data2.segment_index].minea
|
||||
+ lmf_data2.offset;
|
||||
uint32 body_size = lmf_data.offset-sizeof(_lmf_data);
|
||||
if ( body_offset > body_offset + body_size
|
||||
|| body_offset + body_size > perseg[lmf_data2.segment_index].topea )
|
||||
{
|
||||
loader_failure("Corrupted file");
|
||||
}
|
||||
|
||||
file2base(li,
|
||||
at+sizeof(_lmf_data)+sizeof(_lmf_data),
|
||||
body_offset,
|
||||
body_offset + body_size,
|
||||
FILEREG_PATCHABLE);
|
||||
}
|
||||
break;
|
||||
|
||||
case _LMF_FIXUP_SEG_REC:
|
||||
{
|
||||
fixup_data_t fd(FIXUP_SEG16);
|
||||
uint32 n_fixups;
|
||||
_lmf_seg_fixup lmf_seg_fixup;
|
||||
n_fixups = lmf_data.offset / sizeof(_lmf_seg_fixup);
|
||||
while ( n_fixups-- )
|
||||
{
|
||||
lread(li, &lmf_seg_fixup, sizeof(_lmf_seg_fixup));
|
||||
uint32 ea=lmf_seg_fixup.data[0].fixup_offset;
|
||||
if ( lmf_seg_fixup.data[0].fixup_seg_index >= n_segments )
|
||||
loader_failure("Corrupted file");
|
||||
ea += perseg[ lmf_seg_fixup.data[0].fixup_seg_index ].minea; // fix!
|
||||
if ( perseg[ lmf_seg_fixup.data[0].fixup_seg_index ].minea > ea
|
||||
|| ea > perseg[ lmf_seg_fixup.data[0].fixup_seg_index ].topea )
|
||||
{
|
||||
loader_failure("Corrupted file");
|
||||
}
|
||||
fd.sel = get_word(ea); //lmf_seg_fixup.data[0].fixup_seg_index;
|
||||
fd.set(ea);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case _LMF_FIXUP_80X87_REC: // x87 FPU instruction offsets
|
||||
break;
|
||||
|
||||
case _LMF_EOF_REC: // no interesting for ida
|
||||
break;
|
||||
|
||||
case _LMF_RESOURCE_REC: // don't support now
|
||||
break;
|
||||
|
||||
case _LMF_ENDDATA_REC: // 6 bytes of uknown data
|
||||
break;
|
||||
|
||||
case _LMF_FIXUP_LINEAR_REC:
|
||||
break;
|
||||
|
||||
case _LMF_PHRESOURCE: // don't support now
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
uint32 itxt = 0;
|
||||
uint32 idat = 0;
|
||||
for ( nseg = 0; nseg < n_segments; nseg++ )
|
||||
{
|
||||
uint32 selector = LDT_SELECTOR(nseg);
|
||||
char seg_name[8];
|
||||
const char *seg_class;
|
||||
|
||||
if ( (ex.segsizes[nseg]>>28) == _LMF_CODE )
|
||||
{
|
||||
qsnprintf(seg_name, sizeof(seg_name), "cseg_%.02u", ++itxt);
|
||||
seg_class = CLASS_CODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
qsnprintf(seg_name, sizeof(seg_name), "dseg_%.02u", ++idat);
|
||||
seg_class = CLASS_DATA;
|
||||
}
|
||||
|
||||
set_selector(selector, ISFLAT ? 0 : perseg[nseg].minea>>4);
|
||||
|
||||
segment_t s;
|
||||
s.sel = selector;
|
||||
s.start_ea = perseg[nseg].minea;
|
||||
s.end_ea = perseg[nseg].topea;
|
||||
s.align = saRelByte;
|
||||
s.comb = scPub;
|
||||
s.bitness = (_PCF_32BIT & ex.lmf_definition.cflags) ? 1 : 0;
|
||||
bool sparse = (perseg[nseg].topea - perseg[nseg].minea) > filelen;
|
||||
int flags = (sparse ? ADDSEG_SPARSE : 0) | ADDSEG_NOSREG;
|
||||
if ( !add_segm_ex(&s, seg_name, seg_class, flags) )
|
||||
loader_failure();
|
||||
if ( _PCF_32BIT &ex.lmf_definition.cflags )
|
||||
set_segm_addressing(getseg(perseg[nseg].minea), 1); // 32bit
|
||||
}
|
||||
|
||||
set_default_dataseg(LDT_SELECTOR(ex.lmf_definition.argv_index));
|
||||
|
||||
|
||||
|
||||
create_filename_cmt();
|
||||
add_pgm_cmt("Version : %d.%d",
|
||||
ex.lmf_definition.version_no>>8,
|
||||
ex.lmf_definition.version_no&255);
|
||||
|
||||
add_pgm_cmt("Priv level : %d",
|
||||
(_PCF_PRIVMASK &ex.lmf_definition.cflags)>>2);
|
||||
|
||||
char str[MAXSTR], *p = str;
|
||||
char *e = str + sizeof(str);
|
||||
|
||||
|
||||
if ( _PCF_LONG_LIVED & ex.lmf_definition.cflags )
|
||||
APPEND(p, e, " LONG_LIVED");
|
||||
if ( _PCF_32BIT & ex.lmf_definition.cflags )
|
||||
{
|
||||
if ( p != str )
|
||||
APPCHAR(p, e, ',');
|
||||
APPEND(p, e, " 32BIT");
|
||||
}
|
||||
if ( ISFLAT )
|
||||
{
|
||||
if ( p != str )
|
||||
APPCHAR(p, e, ',');
|
||||
APPEND(p, e, " FLAT");
|
||||
}
|
||||
if ( _PCF_NOSHARE & ex.lmf_definition.cflags )
|
||||
{
|
||||
if ( p != str )
|
||||
APPCHAR(p, e, ',');
|
||||
APPEND(p, e, " NOSHARE");
|
||||
}
|
||||
if ( p == str ) APPEND(p, e, " None");
|
||||
add_pgm_cmt("Code flags :%s", str);
|
||||
|
||||
// ig 08.09.00: Automatically load the Watcom signature file
|
||||
plan_to_apply_idasgn(ISFLAT ? "wa32qnx" : "wa16qnx");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
25
idasdk76/ldr/readme.txt
Normal file
25
idasdk76/ldr/readme.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
This directory contains file loaders.
|
||||
|
||||
aif ARM Image File
|
||||
amiga Amige Hunk File
|
||||
aof ARM Object File
|
||||
aout a.out
|
||||
dos MS DOS File
|
||||
dump Memory Dump File
|
||||
geos GEOS File
|
||||
hex Intel/Motorola HEX File
|
||||
hpsom HP SOM
|
||||
intelomf Intel Object File
|
||||
javaldr Java Class Loader
|
||||
mas Macro Assembler
|
||||
nlm Netware Loader Module
|
||||
os9 FLEX/9
|
||||
pef Portable Executable Format (MAC)
|
||||
pilot Palm Pilot
|
||||
qnx Qnx
|
||||
rt11 RT/11
|
||||
w32run Watcom RUN32
|
||||
|
||||
|
||||
Compile them as usual (see how to compile processor modules, for example)
|
||||
14
idasdk76/ldr/rt11/makefile
Normal file
14
idasdk76/ldr/rt11/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=rt11
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)rt11$(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/pdp11/pdp_ml.h ../idaldr.h \
|
||||
rt11.cpp
|
||||
351
idasdk76/ldr/rt11/rt11.cpp
Normal file
351
idasdk76/ldr/rt11/rt11.cpp
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA)
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* E-mail: ig@datarescue.com
|
||||
* RT11 executable Loader.
|
||||
* Copyright (c) 1995-2006 by Iouri Kharon.
|
||||
* E-mail: yjh@styx.cabel.net
|
||||
*
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
L O A D E R for RT11 .sav-files
|
||||
*/
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "../../module/pdp11/pdp_ml.h"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// 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 *filename)
|
||||
{
|
||||
uint64 fsize = qlsize(li);
|
||||
|
||||
if ( (fsize % 512) || !fsize )
|
||||
return 0;
|
||||
qlseek(li, 040);
|
||||
|
||||
ushort tmp;
|
||||
lread2bytes(li, &tmp, 0);
|
||||
if ( tmp > fsize || (tmp & 1) || tmp < 0400 )
|
||||
return 0;
|
||||
lread2bytes(li, &tmp, 0);
|
||||
if ( tmp > fsize )
|
||||
return 0;
|
||||
qlseek(li, 050);
|
||||
lread2bytes(li, &tmp, 0);
|
||||
if ( tmp & 1 || tmp > fsize )
|
||||
return 0;
|
||||
|
||||
// 20.11.01, ig
|
||||
// got tired of too many false positives
|
||||
// now we'll check the file extension
|
||||
|
||||
const char *ext = get_file_ext(filename);
|
||||
if ( ext == NULL || stricmp(ext, "sav") != 0 )
|
||||
return 0;
|
||||
|
||||
*fileformatname = "RT11 (pdp11) sav-file";
|
||||
*processor = "pdp11";
|
||||
return f_LOADER;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void loadchunk(
|
||||
linput_t *li,
|
||||
ea_t ea,
|
||||
size_t size,
|
||||
ea_t base,
|
||||
int32 fpos,
|
||||
const char *sclass)
|
||||
{
|
||||
qoff64_t p = qltell(li);
|
||||
file2base(li, fpos, ea, ea+size, FILEREG_PATCHABLE);
|
||||
add_segm(base, ea, ea+size, NULL, sclass);
|
||||
qlseek(li, p);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// load file into the database.
|
||||
//
|
||||
|
||||
void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/)
|
||||
{
|
||||
set_processor_type("pdp11", SETPROC_LOADER);
|
||||
|
||||
pdp_ml_t *ml = NULL;
|
||||
netnode *ml_ovrtrans = NULL;
|
||||
if ( !pdp11_module_t::get_ml_ptr(&ml, &ml_ovrtrans)
|
||||
|| !ml
|
||||
|| !ml_ovrtrans )
|
||||
{
|
||||
error("Internal error in loader<->module link");
|
||||
}
|
||||
//
|
||||
// Find out asect section and load it
|
||||
//
|
||||
int i;
|
||||
segment_t s;
|
||||
s.start_ea = to_ea(inf_get_baseaddr(), 0);
|
||||
qlseek(li, 040);
|
||||
ushort startIP, topPrg, svrEnd, ovt;
|
||||
lread(li, &startIP, sizeof(ushort));
|
||||
lread(li, &ml->asect_top, sizeof(ushort));
|
||||
if ( (startIP & 1) || startIP < 0400 )
|
||||
startIP = 0;
|
||||
else
|
||||
inf_set_start_ip(startIP);
|
||||
qlseek(li, 050);
|
||||
lread(li, &topPrg, sizeof(ushort));
|
||||
if ( topPrg & 1 || (uint64)topPrg > qlsize(li) )
|
||||
topPrg = 0;
|
||||
if ( topPrg > 01000
|
||||
&& ml->asect_top < (topPrg - 01000 )
|
||||
&& ml->asect_top > 0400 )
|
||||
{
|
||||
svrEnd = ml->asect_top;
|
||||
if ( ml->asect_top > 01000 )
|
||||
svrEnd = 01000;
|
||||
}
|
||||
else
|
||||
{
|
||||
ml->asect_top = svrEnd = 01000;
|
||||
}
|
||||
if ( startIP && ml->asect_top > startIP )
|
||||
{
|
||||
svrEnd = 01000;
|
||||
if ( svrEnd > startIP )
|
||||
svrEnd = startIP;
|
||||
s.end_ea = s.start_ea + svrEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.end_ea = s.start_ea + ml->asect_top;
|
||||
}
|
||||
inf_set_start_cs(inf_get_baseaddr());
|
||||
file2base(li, 0, s.start_ea, s.end_ea, FILEREG_PATCHABLE);
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = find_selector(inf_get_baseaddr());
|
||||
add_segm_ex(&s, "asect", NULL, ADDSEG_NOSREG);
|
||||
|
||||
if ( inf_get_start_ip() != BADADDR )
|
||||
op_plain_offset(s.start_ea + 040, 0, s.start_ea);
|
||||
else
|
||||
create_word(s.start_ea + 040, 2);
|
||||
create_word(s.start_ea + 042, 2); // begin stack value
|
||||
create_word(s.start_ea + 044, 2); // JSW
|
||||
create_word(s.start_ea + 046, 2); // load USR address
|
||||
create_word(s.start_ea + 050, 2); // top programm loading address
|
||||
|
||||
ushort begovrtbl = get_word(s.start_ea + 064);
|
||||
ea_t ei;
|
||||
for ( ei = s.start_ea; ei < s.start_ea + 040; ei += 2 )
|
||||
{
|
||||
if ( get_word(ei) )
|
||||
{
|
||||
create_word(ei, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
del_value(ei);
|
||||
del_value(ei+1);
|
||||
}
|
||||
}
|
||||
for ( ei = s.start_ea + 052; ei < s.end_ea; ei += 2 )
|
||||
{
|
||||
if ( get_word(ei) )
|
||||
{
|
||||
create_word(ei, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
del_value(ei);
|
||||
del_value(ei+1);
|
||||
}
|
||||
}
|
||||
|
||||
ovt = ml->asect_top;
|
||||
if ( s.end_ea != (s.start_ea + ml->asect_top) )
|
||||
{
|
||||
loadchunk(li, s.end_ea, ml->asect_top - svrEnd, inf_get_baseaddr(), svrEnd, "USER");
|
||||
s.end_ea += (ml->asect_top - svrEnd);
|
||||
ml->asect_top = svrEnd;
|
||||
}
|
||||
|
||||
if ( get_word(s.start_ea + 044) & 01000 )
|
||||
{
|
||||
if ( begovrtbl == 0 )
|
||||
{
|
||||
static const ushort chkold[] = { 010046, 010146, 010246, 0421, 010001, 062701 };
|
||||
qlseek(li, ovt);
|
||||
ushort temp;
|
||||
for ( i = 0; i < sizeof(chkold)/2; i++ )
|
||||
{
|
||||
lread(li, &temp, sizeof(ushort));
|
||||
if ( temp != chkold[i] )
|
||||
goto nons;
|
||||
}
|
||||
lread(li, &temp, sizeof(ushort));
|
||||
if ( temp != ovt + 076 )
|
||||
goto nons;
|
||||
qlseek(li, ovt + 0100);
|
||||
lread(li, &temp, sizeof(ushort));
|
||||
if ( temp != 0104376 )
|
||||
goto nons;
|
||||
lread(li, &temp, sizeof(ushort));
|
||||
if ( temp != 0175400 )
|
||||
{
|
||||
nons:
|
||||
warning("OLD-style overlay not implemented.");
|
||||
goto stdload;
|
||||
}
|
||||
begovrtbl = ovt + 0104;
|
||||
warning("Loader overlay v3 is not fully tested.");
|
||||
}
|
||||
else
|
||||
{
|
||||
qlseek(li, begovrtbl);
|
||||
}
|
||||
ushort root_top;
|
||||
lread(li, &root_top, sizeof(ushort));
|
||||
if ( root_top == 0 || (root_top & 1) || root_top >= topPrg )
|
||||
{
|
||||
warning("Illegal overlay structure. Not implemented.");
|
||||
goto stdload;
|
||||
}
|
||||
msg("loading overlay program...\n");
|
||||
netnode temp; // temporary array for overlay start addresses
|
||||
temp.create();
|
||||
// load root module at the end of asect (& USER)
|
||||
inf_set_start_cs(inf_get_baseaddr()+2);
|
||||
loadchunk(li, s.end_ea += 0x20, root_top - ovt, inf_get_start_cs(), ovt, "ROOT");
|
||||
add_segment_translation(inf_get_start_cs()<<4,
|
||||
inf_get_baseaddr()<<4); // translate to asect
|
||||
ushort loadAddr = root_top, fileBlock, ovrsizeW,
|
||||
oldBase = 0, numOvr = 0, numSeg = 0;
|
||||
char name[8] = "ov";
|
||||
for ( i = 6; loadAddr != 04537; begovrtbl += 6, i += 6 )
|
||||
{
|
||||
if ( loadAddr != oldBase )
|
||||
{
|
||||
oldBase = loadAddr;
|
||||
++numOvr;
|
||||
numSeg = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++numSeg;
|
||||
}
|
||||
qsnprintf(&name[2], sizeof(name)-2, "%02d_%02d", numOvr, numSeg);
|
||||
lread(li, &fileBlock, sizeof(ushort));// file block number
|
||||
lread(li, &ovrsizeW, sizeof(ushort)); // segment size in words
|
||||
ovrsizeW <<= 1; // in bytes
|
||||
uint32 ovrstart = (inf_get_max_ea() & ~0xF) + (loadAddr & 0xF) + 0x10;
|
||||
uint32 sel_l = ushort((ovrstart >> 4) - (loadAddr >> 4));
|
||||
loadchunk(li, ovrstart+2, ovrsizeW-2, sel_l, fileBlock*512L+2, "OVR");
|
||||
add_segment_translation(sel_l<<4, inf_get_baseaddr()<<4); // translate to asect
|
||||
add_segment_translation(sel_l<<4, inf_get_start_cs()<<4); // translate to main
|
||||
segment_t *s2 = getseg(ovrstart+2);
|
||||
s2->ovrname = ((uint32)numOvr << 16) | numSeg;
|
||||
set_segm_name(s2, name);
|
||||
temp.altset(i, ovrstart - loadAddr);
|
||||
lread(li, &loadAddr, sizeof(ushort)); // segment loading address
|
||||
}
|
||||
// Entry points loading
|
||||
ml->ovrcallbeg = begovrtbl;
|
||||
for ( ; loadAddr == 04537; begovrtbl += 8 )
|
||||
{
|
||||
ushort ovrentry, ovrind, ovraddr;
|
||||
lread(li, &ovrentry, sizeof(ushort)); // overlay entry-
|
||||
lread(li, &ovrind, sizeof(ushort)); // index+6 in the segments table
|
||||
lread(li, &ovraddr, sizeof(ushort)); // segment entry point
|
||||
ml_ovrtrans->altset(begovrtbl, temp.altval(ovrind) + ovraddr);
|
||||
lread(li, &loadAddr, sizeof(ushort)); // next jsr R5,@#
|
||||
}
|
||||
ml->ovrcallend = begovrtbl - 8;
|
||||
temp.kill();
|
||||
ea_t base = s.end_ea - ovt + ml->ovrcallbeg;
|
||||
i = ml->ovrcallend - ml->ovrcallbeg + 8;
|
||||
set_segm_start(s.end_ea, base+i, SEGMOD_KILL);
|
||||
set_segm_name(getseg(base+i), "main");
|
||||
loadchunk(li, base -= 0x10, i, inf_get_baseaddr()+1, ml->ovrcallbeg, "TBL");
|
||||
ml->ovrtbl_base = (uint32)to_ea(inf_get_baseaddr()+1, 0);
|
||||
set_segm_name(getseg(base), "ov_call");
|
||||
char labname[17] = "cl_";
|
||||
for ( int j = 0; j < i; j += 8 )
|
||||
{
|
||||
uint32 trans = (uint32)ml_ovrtrans->altval(ml->ovrcallbeg+j);
|
||||
qstring sname;
|
||||
get_segm_name(&sname, getseg(trans));
|
||||
labname[3+7] = '\0';
|
||||
if ( sname == &labname[3] )
|
||||
{
|
||||
++numSeg;
|
||||
}
|
||||
else
|
||||
{
|
||||
numSeg = 1;
|
||||
qstrncpy(&labname[3], sname.c_str(), sizeof(labname)-3);
|
||||
}
|
||||
qsnprintf(&labname[3+7], sizeof(labname)-3-7, "_en%02d", numSeg);
|
||||
auto_make_code(trans);
|
||||
set_name(trans, &labname[3], SN_IDBENC);
|
||||
set_name(base + j, labname, SN_IDBENC);
|
||||
create_word(base + j, 2*3);
|
||||
op_plain_offset(base + j + 6, 0, get_segm_base(getseg(trans)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Load regular file/load root of overlay
|
||||
//
|
||||
stdload:
|
||||
loadchunk(li, s.end_ea, qlsize(li) - ovt, inf_get_baseaddr(), ovt, "CODE");
|
||||
}
|
||||
ml_ovrtrans->altset(n_asect, ml->asect_top);
|
||||
ml_ovrtrans->altset(n_ovrbeg, ml->ovrcallbeg);
|
||||
ml_ovrtrans->altset(n_ovrend, ml->ovrcallend);
|
||||
ml_ovrtrans->altset(n_asciiX, false);
|
||||
ml_ovrtrans->altset(n_ovrbas, ml->ovrtbl_base);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// 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,
|
||||
};
|
||||
162
idasdk76/ldr/script_ldrs/archldr_tar.py
Normal file
162
idasdk76/ldr/script_ldrs/archldr_tar.py
Normal file
@@ -0,0 +1,162 @@
|
||||
# Sample archive loader: TAR file format
|
||||
# Feel free to improve it, this is just a sample
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import tarfile
|
||||
import shutil
|
||||
import tempfile
|
||||
import idaapi
|
||||
from ida_kernwin import Choose
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def accept_file(li, filename):
|
||||
"""
|
||||
Check input file format.
|
||||
This function will be called one or more times depending on the result value.
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param filename: name of the file, if it is an archive member name then the actual file doesn't exist
|
||||
@return: 0 - no more supported formats
|
||||
string "name" - format name to display in the chooser dialog
|
||||
dictionary {
|
||||
'format': "name",
|
||||
'options': integer,
|
||||
'flags': integer
|
||||
}
|
||||
options: should be 1,
|
||||
if ORed with ACCEPT_ARCHIVE then it is an archive loader
|
||||
if ORed with ACCEPT_CONTINUE then this function will be called another time
|
||||
if ORed with ACCEPT_FIRST then indicates preferred format
|
||||
loader_flags: see GENFLG_
|
||||
"""
|
||||
li.seek(0)
|
||||
try:
|
||||
t = tarfile.open(fileobj=li, mode='r|*')
|
||||
t.close()
|
||||
(_, ext) = os.path.splitext(filename)
|
||||
if ext not in (".tar", ".tgz", "tar.gz"):
|
||||
return 0
|
||||
return {'format': "TAR archive",
|
||||
'options': 1 | idaapi.ACCEPT_ARCHIVE}
|
||||
except Exception:
|
||||
pass
|
||||
return 0
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def _read_whole_file(li):
|
||||
li.seek(0)
|
||||
return li.read(li.size())
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def _tmpnam():
|
||||
(h, n) = tempfile.mkstemp()
|
||||
os.close(h)
|
||||
return n
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
class TarMemberChoose(Choose):
|
||||
"""
|
||||
TAR archive members selection chooser
|
||||
"""
|
||||
|
||||
def __init__(self, archive, items):
|
||||
title = "Archive: " + archive
|
||||
Choose.__init__(
|
||||
self,
|
||||
title,
|
||||
[["File name", Choose.CHCOL_PATH | 60],
|
||||
["Size", Choose.CHCOL_DEC | 10]],
|
||||
icon=-1, y1=-2,
|
||||
flags = Choose.CH_MODAL | Choose.CH_NOIDB)
|
||||
self.items = items
|
||||
|
||||
def OnGetLine(self, n):
|
||||
return [self.items[n].name, str(self.items[n].size)]
|
||||
|
||||
def OnGetSize(self):
|
||||
return len(self.items)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def process_archive(li, archive, defmember, neflags, formatname):
|
||||
"""
|
||||
Display list of archive members and let the user select one.
|
||||
Extract the selected archive member into a temporary file.
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param archive: name of archive
|
||||
@param defmember: extract the specified member
|
||||
@param neflags: options selected by the user, see loader.hpp
|
||||
@param formatname: name of type of the file
|
||||
|
||||
@return: '' cancelled by the user
|
||||
string error message
|
||||
dictionary {
|
||||
'temp_file': string,
|
||||
'module_name': string,
|
||||
'neflags': integer
|
||||
}
|
||||
temp_file: name of the file with the extracted archive member
|
||||
module_name: name of the extracted archive member
|
||||
neflags: options selected by the user, see loader.hpp
|
||||
"""
|
||||
li.seek(0)
|
||||
try:
|
||||
t = tarfile.open(fileobj=li, mode='r|*')
|
||||
except tarfile.TarError as e:
|
||||
return str(e)
|
||||
|
||||
# list of archive members,
|
||||
members = t.getmembers()
|
||||
t.close()
|
||||
|
||||
# we are interested in regular files only
|
||||
items = [members[i] for i in range(0, len(members))]
|
||||
|
||||
# if default archive member is specified
|
||||
if defmember:
|
||||
for m in items:
|
||||
if os.path.basename(m.name) == defmember:
|
||||
selected_item = m
|
||||
break
|
||||
else:
|
||||
return "Unknown TAR archive default member: %s" % defmember
|
||||
else:
|
||||
chooser = TarMemberChoose(archive, items)
|
||||
code = chooser.Show(True)
|
||||
if code == Choose.NO_SELECTION:
|
||||
return "" # user canceled
|
||||
selected_item = items[code]
|
||||
|
||||
# construct archive member name
|
||||
member_name = os.path.basename(selected_item.name)
|
||||
module_name = os.path.join(os.path.dirname(archive), member_name)
|
||||
|
||||
# file for archive member
|
||||
workfile = _tmpnam()
|
||||
|
||||
# extract member
|
||||
# there is a bug reported in 2010 year but not fixed yet:
|
||||
# http://bugs.python.org/issue10436
|
||||
li.seek(0)
|
||||
buf = _read_whole_file(li)
|
||||
(h, workfile_tar) = tempfile.mkstemp()
|
||||
os.write(h, buf)
|
||||
os.close(h)
|
||||
|
||||
t = tarfile.open(name=workfile_tar, mode='r:*')
|
||||
tarinfo = t.getmember(selected_item.name)
|
||||
f_in = t.extractfile(tarinfo)
|
||||
f_out = open(workfile, 'wb')
|
||||
shutil.copyfileobj(f_in, f_out)
|
||||
f_out.close()
|
||||
f_in.close()
|
||||
t.close()
|
||||
os.unlink(workfile_tar)
|
||||
|
||||
return {'temp_file': workfile, 'module_name': module_name}
|
||||
74
idasdk76/ldr/script_ldrs/bios_image.idc
Normal file
74
idasdk76/ldr/script_ldrs/bios_image.idc
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
|
||||
Sample IDC loader: load BIOS image
|
||||
|
||||
Feel free to improve it, this is just a sample
|
||||
|
||||
*/
|
||||
|
||||
#include <idc.idc>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Verify the input file format
|
||||
// li - loader_input_t object. it is positioned at the file start
|
||||
// Returns: if the input file is not recognized
|
||||
// return 0
|
||||
// else
|
||||
// return object with 2 attributes:
|
||||
// format: description of the file format
|
||||
// options:1 or ACCEPT_FIRST. it is ok not to set this attribute.
|
||||
// or return a string designating the format name
|
||||
|
||||
static accept_file(li, filename)
|
||||
{
|
||||
if ( li.size() > 0x10000 ) // we support max 64K images
|
||||
return 0;
|
||||
|
||||
li.seek(-16, SEEK_END);
|
||||
if ( li.getc() != 0xEA ) // jmp?
|
||||
return 0;
|
||||
|
||||
li.seek(-2, SEEK_END);
|
||||
if ( (li.getc() & 0xF0) != 0xF0 ) // reasonable computer type?
|
||||
return 0;
|
||||
|
||||
auto buf;
|
||||
li.seek(-11, SEEK_END);
|
||||
li.read(&buf, 9);
|
||||
// 06/03/08
|
||||
if ( buf[2] != "/" || buf[5] != "/" || buf[8] != "\x00" )
|
||||
return 0;
|
||||
|
||||
// accept the file
|
||||
auto res = object();
|
||||
res.format = "BIOS Image"; // description of the file format
|
||||
return res;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Load the file into the database
|
||||
// li - loader_input_t object. it is positioned at the file start
|
||||
// neflags - combination of NEF_... bits describing how to load the file
|
||||
// probably NEF_MAN is the most interesting flag that can
|
||||
// be used to select manual loading
|
||||
// format - description of the file format
|
||||
// Returns: 1 - means success, 0 - failure
|
||||
static load_file(li, neflags, format)
|
||||
{
|
||||
set_processor_type("metapc", SETPROC_LOADER);
|
||||
|
||||
auto base = 0xF000;
|
||||
auto start = base << 4;
|
||||
auto size = li.size();
|
||||
|
||||
// copy bytes to the database
|
||||
loadfile(li, 0, base<<4, size);
|
||||
|
||||
// create a segment
|
||||
add_segm_ex(start, start+size, base, 0, saRelPara, scPub, ADDSEG_NOSREG);
|
||||
|
||||
// set the entry registers
|
||||
set_inf_attr(INF_START_IP, size-16);
|
||||
set_inf_attr(INF_START_CS, base);
|
||||
return 1;
|
||||
}
|
||||
114
idasdk76/ldr/script_ldrs/bios_image.py
Normal file
114
idasdk76/ldr/script_ldrs/bios_image.py
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
import sys
|
||||
|
||||
import idaapi
|
||||
import idc
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def accept_file(li, filename):
|
||||
# ignore any trailer; align on 64KB boundary
|
||||
|
||||
size = li.size()
|
||||
if (size & 0xFFF) != 0:
|
||||
size &= ~0xFFFF
|
||||
|
||||
if size < 16:
|
||||
return 0
|
||||
|
||||
# check the code at F000:FFF0
|
||||
li.seek(size-16);
|
||||
jump = li.read(16)
|
||||
# skip any nops
|
||||
while jump[:1] == b'\x90':
|
||||
jump = jump[1:]
|
||||
# skip wbinvd
|
||||
if jump.startswith(b'\x0F\x09'):
|
||||
jump = jump[2:]
|
||||
|
||||
_byte = ord if sys.version_info.major < 3 else lambda t: t
|
||||
|
||||
# is it a jump?
|
||||
if (
|
||||
jump.startswith(b'\xEA') # jmp ptr16:16 EA oo oo ss ss
|
||||
and len(jump) >= 5
|
||||
and 0xF0 <= _byte(jump[4]) <= 0xFE # segment should be above F000
|
||||
) or (
|
||||
jump.startswith(b'\xE9') # jmp rel16 E9 ll hh
|
||||
and len(jump) >= 3
|
||||
# and (_byte(jump[2]) & 0x80) != 0 # jump backwards
|
||||
) or (
|
||||
jump.startswith(b'\xEB') # jmp rel8 EB dd
|
||||
and len(jump) >= 2
|
||||
and (_byte(jump[1]) & 0x80) != 0 # jump backwards
|
||||
):
|
||||
return {'format': "BIOS Image", 'processor':'metapc'} # accept the file
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def myAddSeg(startea, endea, base, use32, name, clas):
|
||||
s = idaapi.segment_t()
|
||||
s.start_ea = startea
|
||||
s.end_ea = endea
|
||||
s.sel = idaapi.setup_selector(base)
|
||||
s.bitness = use32
|
||||
s.align = idaapi.saRelPara
|
||||
s.comb = idaapi.scPub
|
||||
idaapi.add_segm_ex(s, name, clas, idaapi.ADDSEG_NOSREG|idaapi.ADDSEG_OR_DIE)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def load_file(li, neflags, format):
|
||||
chunksize = 0x10000
|
||||
base = 0xF000
|
||||
start = base << 4;
|
||||
size = li.size()
|
||||
if (size & 0xFFF) != 0:
|
||||
size &= ~0xFFFF
|
||||
offs = size - chunksize
|
||||
|
||||
idaapi.set_processor_type("metapc", idaapi.SETPROC_LOADER)
|
||||
|
||||
if size < chunksize:
|
||||
offs = 0
|
||||
start += (chunksize - size)
|
||||
chunksize = size
|
||||
|
||||
# make E and F segments for real-mode part
|
||||
myAddSeg(start, start+chunksize, base, 0, "BIOS_F", "CODE")
|
||||
li.file2base(offs, start, start+chunksize, 1)
|
||||
if offs > 0 and base > 0xE000:
|
||||
base -= 0x1000
|
||||
start -= chunksize
|
||||
offs -= chunksize
|
||||
myAddSeg(start, start+chunksize, base, 0, "BIOS_%X" % (base>>12), "CODE")
|
||||
li.file2base(offs, start, start+chunksize, 1)
|
||||
# set default ds to point to the current segment
|
||||
idc.set_default_sreg_value(start, "ds", base)
|
||||
|
||||
if offs > 0:
|
||||
# file is bigger than 128KB
|
||||
# make a flat 32-bit segment for the flash alias area
|
||||
start = (-size) & 0xFFFFFFFF # place it so that it ends at 4GB
|
||||
chunksize = size
|
||||
if not idc.__EA64__:
|
||||
chunksize -= 2 # truncate last two bytes to avoid address space overlap
|
||||
# map the whole file
|
||||
offs = 0
|
||||
base = 0
|
||||
myAddSeg(start, start+chunksize, base, 1, "BIOS_FLASH", "CODE")
|
||||
li.file2base(offs, start, start+chunksize, 1)
|
||||
|
||||
# set the entry registers to F000:FFF0
|
||||
idc.set_inf_attr(idc.INF_START_IP, 0xFFF0)
|
||||
idc.set_inf_attr(idc.INF_START_CS, 0xF000)
|
||||
# turn off "Convert 32bit instruction operand to offset", too many false positives in high areas
|
||||
idc.set_inf_attr(idc.INF_AF, idc.get_inf_attr(idc.INF_AF) & ~idc.AF_IMMOFF)
|
||||
# turn off "Create function tails"
|
||||
idc.set_inf_attr(idc.INF_AF, idc.get_inf_attr(idc.INF_AF) & ~idc.AF_FTAIL)
|
||||
|
||||
return 1
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def move_segm(frm, to, sz, fileformatname):
|
||||
idc.warning("move_segm(from=%s, to=%s, sz=%d, formatname=%s" % (hex(frm), hex(to), sz, fileformatname))
|
||||
return 0
|
||||
600
idasdk76/ldr/script_ldrs/hppacore.idc
Normal file
600
idasdk76/ldr/script_ldrs/hppacore.idc
Normal file
@@ -0,0 +1,600 @@
|
||||
//
|
||||
// Loader for HP-UX PA-Risc core dumps that are not ELF
|
||||
//
|
||||
// Avi Cohen Stuart avi.cohenstuart@infor.com
|
||||
// August 2010
|
||||
//
|
||||
// The core image exists of sections defined by the types below
|
||||
//struct corehead {
|
||||
// int type;
|
||||
// uint space;
|
||||
// uint addr;
|
||||
// uint len;
|
||||
//};
|
||||
//
|
||||
// Analysing a core file can be tedious without the binary that
|
||||
// caused the crash.
|
||||
//
|
||||
// Note that the CORE_PROC section contains information about the
|
||||
// state of the process. See the proc_info in /usr/include/sys/core.h on
|
||||
// a HP-UX PA-Risc machine.
|
||||
//
|
||||
#include <idc.idc>
|
||||
|
||||
#define CORE_NONE 0x00000000 /* reserved for future use */
|
||||
#define CORE_FORMAT 0x00000001 /* core version */
|
||||
#define CORE_KERNEL 0x00000002 /* kernel version */
|
||||
#define CORE_PROC 0x00000004 /* per process information */
|
||||
#define CORE_TEXT 0x00000008 /* reserved for future use */
|
||||
#define CORE_DATA 0x00000010 /* data of the process */
|
||||
#define CORE_STACK 0x00000020 /* stack of the process */
|
||||
#define CORE_SHM 0x00000040 /* reserved for future use */
|
||||
#define CORE_MMF 0x00000080 /* reserved for future use */
|
||||
#define CORE_EXEC 0x00000100 /* exec information */
|
||||
#define CORE_ANON_SHMEM 0x00000200 /* anonymous shared memory */
|
||||
|
||||
static Structures_0(id) {
|
||||
auto mid;
|
||||
|
||||
id = add_struc(-1,"__reg32_t",0);
|
||||
id = add_struc(-1,"__reg64_t",0);
|
||||
id = add_struc(-1,"__save_state::$8C0FCFCC2B9ACB495244C4B504AA9783",1);
|
||||
id = add_struc(-1,"fp_int_block_t",0);
|
||||
id = add_struc(-1,"fp_dbl_block_t",0);
|
||||
id = add_struc(-1,"__save_state::$F0F3A0B47411777C5961C26FBCE8E4DA",1);
|
||||
id = add_struc(-1,"__ss_narrow_t",0);
|
||||
|
||||
id = add_struc(-1,"save_state_t",0);
|
||||
id = add_struc(-1,"aux_id",0);
|
||||
id = add_struc(-1,"som_exec_auxhdr",0);
|
||||
id = add_struc(-1,"proc_exec::$733C094BD5627056653FFCFE6E9DB4EB",0);
|
||||
id = add_struc(-1,"proc_info",0);
|
||||
id = add_struc(-1,"shl_descriptor",0);
|
||||
id = add_struc(-1,"proc_exec",0);
|
||||
|
||||
id = get_struc_id("__reg32_t");
|
||||
mid = add_struc_member(id,"ss_reserved", 0X0, 0x20000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr1_hi", 0X8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr1_lo", 0XC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_rp_hi", 0X10, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_rp_lo", 0X14, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr3_hi", 0X18, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr3_lo", 0X1C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr4_hi", 0X20, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr4_lo", 0X24, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr5_hi", 0X28, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr5_lo", 0X2C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr6_hi", 0X30, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr6_lo", 0X34, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr7_hi", 0X38, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr7_lo", 0X3C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr8_hi", 0X40, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr8_lo", 0X44, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr9_hi", 0X48, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr9_lo", 0X4C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr10_hi", 0X50, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr10_lo", 0X54, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr11_hi", 0X58, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr11_lo", 0X5C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr12_hi", 0X60, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr12_lo", 0X64, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr13_hi", 0X68, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr13_lo", 0X6C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr14_hi", 0X70, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr14_lo", 0X74, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr15_hi", 0X78, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr15_lo", 0X7C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr16_hi", 0X80, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr16_lo", 0X84, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr17_hi", 0X88, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr17_lo", 0X8C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr18_hi", 0X90, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr18_lo", 0X94, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr19_hi", 0X98, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr19_lo", 0X9C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr20_hi", 0XA0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr20_lo", 0XA4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr21_hi", 0XA8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr21_lo", 0XAC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr22_hi", 0XB0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr22_lo", 0XB4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg3_hi", 0XB8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg3_lo", 0XBC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg2_hi", 0XC0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg2_lo", 0XC4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg1_hi", 0XC8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg1_lo", 0XCC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg0_hi", 0XD0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg0_lo", 0XD4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_dp_hi", 0XD8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_dp_lo", 0XDC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_ret0_hi", 0XE0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_ret0_lo", 0XE4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_ret1_hi", 0XE8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_ret1_lo", 0XEC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sp_hi", 0XF0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sp_lo", 0XF4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr31_hi", 0XF8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr31_lo", 0XFC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr11_hi", 0X100, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr11_lo", 0X104, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcoq_head_hi", 0X108, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcoq_head_lo", 0X10C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcsq_head_hi", 0X110, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcsq_head_lo", 0X114, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcoq_tail_hi", 0X118, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcoq_tail_lo", 0X11C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcsq_tail_hi", 0X120, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcsq_tail_lo", 0X124, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr15_hi", 0X128, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr15_lo", 0X12C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr19_hi", 0X130, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr19_lo", 0X134, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr20_hi", 0X138, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr20_lo", 0X13C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr21_hi", 0X140, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr21_lo", 0X144, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr22_hi", 0X148, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr22_lo", 0X14C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cpustate_hi", 0X150, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cpustate_lo", 0X154, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr4_hi", 0X158, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr4_lo", 0X15C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr0_hi", 0X160, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr0_lo", 0X164, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr1_hi", 0X168, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr1_lo", 0X16C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr2_hi", 0X170, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr2_lo", 0X174, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr3_hi", 0X178, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr3_lo", 0X17C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr5_hi", 0X180, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr5_lo", 0X184, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr6_hi", 0X188, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr6_lo", 0X18C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr7_hi", 0X190, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr7_lo", 0X194, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr0_hi", 0X198, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr0_lo", 0X19C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr8_hi", 0X1A0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr8_lo", 0X1A4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr9_hi", 0X1A8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr9_lo", 0X1AC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr10_hi", 0X1B0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr10_lo", 0X1B4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr12_hi", 0X1B8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr12_lo", 0X1BC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr13_hi", 0X1C0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr13_lo", 0X1C4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr24_hi", 0X1C8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr24_lo", 0X1CC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr25_hi", 0X1D0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr25_lo", 0X1D4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr26_hi", 0X1D8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr26_lo", 0X1DC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr27_hi", 0X1E0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr27_lo", 0X1E4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_reserved2", 0X1E8, 0x20000400, -1, 16);
|
||||
mid = add_struc_member(id,"ss_oldcksum", 0X1F8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_newcksum", 0X1FC, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("__reg64_t");
|
||||
mid = add_struc_member(id,"ss_reserved", 0X0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr1", 0X8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_rp", 0X10, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr3", 0X18, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr4", 0X20, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr5", 0X28, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr6", 0X30, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr7", 0X38, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr8", 0X40, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr9", 0X48, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr10", 0X50, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr11", 0X58, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr12", 0X60, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr13", 0X68, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr14", 0X70, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr15", 0X78, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr16", 0X80, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr17", 0X88, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr18", 0X90, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr19", 0X98, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr20", 0XA0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr21", 0XA8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr22", 0XB0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_arg3", 0XB8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_arg2", 0XC0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_arg1", 0XC8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_arg0", 0XD0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_dp", 0XD8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_ret0", 0XE0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_ret1", 0XE8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sp", 0XF0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_gr31", 0XF8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr11", 0X100, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_pcoq_head", 0X108, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_pcsq_head", 0X110, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_pcoq_tail", 0X118, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_pcsq_tail", 0X120, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr15", 0X128, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr19", 0X130, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr20", 0X138, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr21", 0X140, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr22", 0X148, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cpustate", 0X150, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr4", 0X158, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr0", 0X160, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr1", 0X168, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr2", 0X170, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr3", 0X178, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr5", 0X180, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr6", 0X188, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_sr7", 0X190, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr0", 0X198, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr8", 0X1A0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr9", 0X1A8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr10", 0X1B0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr12", 0X1B8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr13", 0X1C0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr24", 0X1C8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr25", 0X1D0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr26", 0X1D8, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_cr27", 0X1E0, 0x30000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_reserved2", 0X1E8, 0x30000400, -1, 16);
|
||||
mid = add_struc_member(id,"ss_oldcksum", 0X1F8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_newcksum", 0X1FC, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("__save_state::$8C0FCFCC2B9ACB495244C4B504AA9783");
|
||||
mid = add_struc_member(id,"ss_64", 0X0, 0x60000400, get_struc_id("__reg64_t"), 512);
|
||||
mid = add_struc_member(id,"ss_32", 0X0, 0x60000400, get_struc_id("__reg32_t"), 512);
|
||||
|
||||
id = get_struc_id("fp_int_block_t");
|
||||
mid = add_struc_member(id,"ss_fpstat", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept1", 0X4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept2", 0X8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept3", 0XC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept4", 0X10, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept5", 0X14, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept6", 0X18, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpexcept7", 0X1C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp4_hi", 0X20, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp4_lo", 0X24, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp5_hi", 0X28, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp5_lo", 0X2C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp6_hi", 0X30, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp6_lo", 0X34, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp7_hi", 0X38, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp7_lo", 0X3C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp8_hi", 0X40, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp8_lo", 0X44, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp9_hi", 0X48, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp9_lo", 0X4C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp10_hi", 0X50, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp10_lo", 0X54, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp11_hi", 0X58, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp11_lo", 0X5C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp12_hi", 0X60, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp12_lo", 0X64, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp13_hi", 0X68, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp13_lo", 0X6C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp14_hi", 0X70, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp14_lo", 0X74, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp15_hi", 0X78, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp15_lo", 0X7C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp16_hi", 0X80, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp16_lo", 0X84, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp17_hi", 0X88, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp17_lo", 0X8C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp18_hi", 0X90, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp18_lo", 0X94, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp19_hi", 0X98, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp19_lo", 0X9C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp20_hi", 0XA0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp20_lo", 0XA4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp21_hi", 0XA8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp21_lo", 0XAC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp22_hi", 0XB0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp22_lo", 0XB4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp23_hi", 0XB8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp23_lo", 0XBC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp24_hi", 0XC0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp24_lo", 0XC4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp25_hi", 0XC8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp25_lo", 0XCC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp26_hi", 0XD0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp26_lo", 0XD4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp27_hi", 0XD8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp27_lo", 0XDC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp28_hi", 0XE0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp28_lo", 0XE4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp29_hi", 0XE8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp29_lo", 0XEC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp30_hi", 0XF0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp30_lo", 0XF4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp31_hi", 0XF8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fp31_lo", 0XFC, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("fp_dbl_block_t");
|
||||
mid = add_struc_member(id,"ss_fp0", 0X0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp1", 0X8, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp2", 0X10, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp3", 0X18, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp4", 0X20, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp5", 0X28, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp6", 0X30, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp7", 0X38, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp8", 0X40, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp9", 0X48, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp10", 0X50, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp11", 0X58, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp12", 0X60, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp13", 0X68, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp14", 0X70, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp15", 0X78, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp16", 0X80, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp17", 0X88, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp18", 0X90, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp19", 0X98, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp20", 0XA0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp21", 0XA8, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp22", 0XB0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp23", 0XB8, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp24", 0XC0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp25", 0XC8, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp26", 0XD0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp27", 0XD8, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp28", 0XE0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp29", 0XE8, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp30", 0XF0, 0x90000400, -1, 8);
|
||||
mid = add_struc_member(id,"ss_fp31", 0XF8, 0x90000400, -1, 8);
|
||||
|
||||
id = get_struc_id("__save_state::$F0F3A0B47411777C5961C26FBCE8E4DA");
|
||||
mid = add_struc_member(id,"fpdbl", 0X0, 0x60000400, get_struc_id("fp_dbl_block_t"), 256);
|
||||
mid = add_struc_member(id,"fpint", 0X0, 0x60000400, get_struc_id("fp_int_block_t"), 256);
|
||||
|
||||
id = get_struc_id("__ss_narrow_t");
|
||||
mid = add_struc_member(id,"ss_gr1", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_rp", 0X4, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_gr3", 0X8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr4", 0XC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr5", 0X10, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr6", 0X14, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr7", 0X18, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr8", 0X1C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr9", 0X20, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr10", 0X24, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr11", 0X28, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr12", 0X2C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr13", 0X30, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr14", 0X34, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr15", 0X38, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr16", 0X3C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr17", 0X40, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr18", 0X44, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr19", 0X48, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr20", 0X4C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr21", 0X50, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_gr22", 0X54, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_arg3", 0X58, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_arg2", 0X5C, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_arg1", 0X60, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_arg0", 0X64, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_dp", 0X68, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_ret0", 0X6C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_ret1", 0X70, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sp", 0X74, 0x20500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ss_gr31", 0X78, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr11", 0X7C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcoq_head", 0X80, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcsq_head", 0X84, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcoq_tail", 0X88, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_pcsq_tail", 0X8C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr15", 0X90, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr19", 0X94, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr20", 0X98, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr21", 0X9C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr22", 0XA0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cpustate", 0XA4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr4", 0XA8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr0", 0XAC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr1", 0XB0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr2", 0XB4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr3", 0XB8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr5", 0XBC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr6", 0XC0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_sr7", 0XC4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr0", 0XC8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr8", 0XCC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr9", 0XD0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr10", 0XD4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr12", 0XD8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr13", 0XDC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr24", 0XE0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr25", 0XE4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr26", 0XE8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_cr27", 0XEC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_mpsfu_low", 0XF0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_mpsfu_ovflo", 0XF4, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("save_state_t");
|
||||
mid = add_struc_member(id,"ss_flags", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_narrow", 0X4, 0x60000400, get_struc_id("__ss_narrow_t"), 248);
|
||||
mid = add_struc_member(id,"ss_pad", 0XFC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ss_fpblock", 0X100, 0x60000400, get_struc_id("__save_state::$F0F3A0B47411777C5961C26FBCE8E4DA"), 256);
|
||||
mid = add_struc_member(id,"ss_xor", 0X200, 0x000400, -1, 128);
|
||||
mid = add_struc_member(id,"ss_wide", 0X280, 0x60000400, get_struc_id("__save_state::$8C0FCFCC2B9ACB495244C4B504AA9783"), 512);
|
||||
|
||||
id = get_struc_id("proc_info");
|
||||
mid = add_struc_member(id,"sig", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"trap_type", 0X4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"hw_regs", 0X8, 0x60000400, get_struc_id("save_state_t"), 1152);
|
||||
mid = add_struc_member(id,"lwpid", 0X488, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"user_tid", 0X48C, 0x30000400, -1, 8);
|
||||
|
||||
id = get_struc_id("shl_descriptor");
|
||||
mid = add_struc_member(id,"tstart", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"tend", 0X4, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"dstart", 0X8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"dend", 0XC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"ltptr", 0X10, 0x25500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"handle", 0X14, 0x25500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"filename", 0X18, 0x50000400, 0x0, 1025);
|
||||
mid = add_struc_member(id,"initializer", 0X41C, 0x25500400, 0XFFFFFFFF, 4, 0XFFFFFFFF, 0X0, 0x000002);
|
||||
mid = add_struc_member(id,"ref_count", 0X420, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"reserved3", 0X424, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"reserved2", 0X428, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"reserved1", 0X42C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"reserved0", 0X430, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("aux_id");
|
||||
mid = add_struc_member(id,"type", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"length", 0X4, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("som_exec_auxhdr");
|
||||
mid = add_struc_member(id,"som_auxhdr", 0X0, 0x60000400, get_struc_id("aux_id"), 8);
|
||||
mid = add_struc_member(id,"exec_tsize", 0X8, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_tmem", 0XC, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_tfile", 0X10, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_dsize", 0X14, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_dmem", 0X18, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_dfile", 0X1C, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_bsize", 0X20, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_entry", 0X24, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_flags", 0X28, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"exec_bfill", 0X2C, 0x20000400, -1, 4);
|
||||
|
||||
id = get_struc_id("proc_exec::$733C094BD5627056653FFCFE6E9DB4EB");
|
||||
mid = add_struc_member(id,"u_magic", 0X0, 0x20000400, -1, 4);
|
||||
mid = add_struc_member(id,"som_aux", 0X4, 0x60000400, get_struc_id("som_exec_auxhdr"), 48);
|
||||
|
||||
id = get_struc_id("proc_exec");
|
||||
mid = add_struc_member(id,"exdata", 0X0, 0x60000400, get_struc_id("proc_exec::$733C094BD5627056653FFCFE6E9DB4EB"), 52);
|
||||
mid = add_struc_member(id,"cmd", 0X34, 0x50000400, 0x0, 15);
|
||||
mid = add_struc_member(id,"_padding", 0X43, 0x000400, -1, 1);
|
||||
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Information about structure types
|
||||
|
||||
static Structures(void) {
|
||||
auto id;
|
||||
id = Structures_0(id);
|
||||
}
|
||||
|
||||
// End of file.
|
||||
|
||||
static accept_file(li, filename)
|
||||
{
|
||||
auto buf;
|
||||
|
||||
li.seek(16,0); // skip first header
|
||||
li.read(&buf, 6);
|
||||
|
||||
// Magic:
|
||||
if (buf != "HP-UX\0")
|
||||
return 0;
|
||||
return "HP-UX HP-PA Core dump Image (non ELF)";
|
||||
}
|
||||
|
||||
static read_core_head(li)
|
||||
{
|
||||
auto core_type;
|
||||
auto core_space;
|
||||
auto core_addr;
|
||||
auto core_len;
|
||||
|
||||
auto proc_info_addr;
|
||||
auto proc_exec_addr;
|
||||
auto proc_exec_sel;
|
||||
|
||||
proc_info_addr = 0;
|
||||
proc_exec_addr = 0;
|
||||
proc_exec_sel = 0;
|
||||
|
||||
auto ret;
|
||||
auto mf = (get_inf_attr(INF_LFLAGS) & LFLG_MSF) != 0;
|
||||
li.seek(0, 0);
|
||||
ret = 0;
|
||||
// keep reading corehead structs and process them
|
||||
while (1) {
|
||||
ret = li.readbytes(&core_type, 4, mf);
|
||||
if (ret!=0) break;
|
||||
//msg("ret: %d\n", ret);
|
||||
|
||||
ret = li.readbytes(&core_space, 4, mf);
|
||||
ret= li.readbytes(&core_addr, 4, mf);
|
||||
ret= li.readbytes(&core_len, 4, mf);
|
||||
|
||||
//msg("type %x addr %x len %x\n", core_type, core_addr, core_len);
|
||||
|
||||
loadfile(li, li.tell(), core_addr, core_len);
|
||||
|
||||
AddSeg(core_addr, core_addr+core_len, 0, 1, saRelPara, 2);
|
||||
if (core_type==CORE_FORMAT) {
|
||||
set_segm_class(core_addr, "FORMAT");
|
||||
set_segm_type(core_addr, SEG_DATA);
|
||||
}
|
||||
if (core_type==CORE_PROC) {
|
||||
set_segm_class(core_addr, "PROC");
|
||||
set_segm_type(core_addr, SEG_DATA);
|
||||
proc_info_addr = core_addr;
|
||||
}
|
||||
if (core_type==CORE_DATA) {
|
||||
set_segm_class(core_addr, "DATA");
|
||||
set_segm_type(core_addr, SEG_DATA);
|
||||
|
||||
}
|
||||
if (core_type==CORE_STACK) {
|
||||
set_segm_class(core_addr, "STACK");
|
||||
set_segm_type(core_addr, SEG_DATA);
|
||||
}
|
||||
if (core_type==CORE_MMF) {
|
||||
set_segm_class(core_addr, "MMF");
|
||||
}
|
||||
if (core_type==CORE_NONE) {
|
||||
set_segm_class(core_addr, "NONE");
|
||||
}
|
||||
if (core_type==CORE_EXEC) {
|
||||
set_segm_class(core_addr, "EXEC");
|
||||
set_segm_type(core_addr, SEG_DATA);
|
||||
proc_exec_addr = core_addr;
|
||||
proc_exec_sel = get_segm_attr(core_addr, SEGATTR_SEL);
|
||||
}
|
||||
}
|
||||
|
||||
set_inf_attr(INF_COMPILER, COMP_GNU); // closest to HP compiler
|
||||
set_inf_attr(INF_SIZEOF_ALGN, 4);
|
||||
|
||||
Structures();
|
||||
|
||||
if (proc_info_addr !=0) {
|
||||
//provide sime initial information about
|
||||
//the process state
|
||||
msg("set proc_data\n");
|
||||
create_struct(proc_info_addr, -1, "proc_info");
|
||||
}
|
||||
if (proc_exec_addr !=0) {
|
||||
// provide some info about the exec
|
||||
create_struct(proc_exec_addr, -1 , "proc_exec");
|
||||
set_inf_attr(INF_START_IP, proc_exec_addr);
|
||||
set_inf_attr(INF_START_CS, proc_exec_sel);
|
||||
}
|
||||
|
||||
//
|
||||
// from here on, in a future version: locate the binary,
|
||||
// shared libraries and load them as well into the idb...
|
||||
}
|
||||
|
||||
static load_file(li, neflags, format)
|
||||
{
|
||||
set_processor_type("hppa", SETPROC_LOADER);
|
||||
|
||||
msg("file size %d\n", li.size());
|
||||
|
||||
read_core_head(li);
|
||||
|
||||
return 1;
|
||||
}
|
||||
24
idasdk76/ldr/script_ldrs/makefile
Normal file
24
idasdk76/ldr/script_ldrs/makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
include ../../allmake.mak
|
||||
|
||||
LDRDIR = $(R)loaders
|
||||
|
||||
LOADERS += archldr_tar.py
|
||||
LOADERS += bios_image.py
|
||||
LOADERS += pdfldr.py
|
||||
LOADERS += uimage.py
|
||||
LOADERS += wince.py
|
||||
LOADERS-$(IDAADV) += hppacore.idc
|
||||
|
||||
LOADERS += $(LOADERS-1)
|
||||
|
||||
all: $(addprefix $(LDRDIR)/, $(LOADERS))
|
||||
|
||||
$(LDRDIR)/%.idc: %.idc
|
||||
$(CP) $? $@
|
||||
|
||||
$(LDRDIR)/%.py: %.py
|
||||
$(CP) $? $@
|
||||
|
||||
clean::
|
||||
rm -f $(addprefix $(LDRDIR)/, $(LOADERS))
|
||||
319
idasdk76/ldr/script_ldrs/pdfldr.py
Normal file
319
idasdk76/ldr/script_ldrs/pdfldr.py
Normal file
@@ -0,0 +1,319 @@
|
||||
"""
|
||||
A script that extracts shellcode from PDF files
|
||||
|
||||
The script uses very basic shellcode extraction algorithm
|
||||
|
||||
Copyright (c) 1990-2021 Hex-Rays
|
||||
ALL RIGHTS RESERVED.
|
||||
|
||||
Revision history
|
||||
=========================
|
||||
v1.0 - initial version
|
||||
|
||||
|
||||
Possible enhancements:
|
||||
=========================
|
||||
1. From Didier:
|
||||
-----------------
|
||||
FYI: the regex you use to match /JavaScript /JS will fail to match
|
||||
name obfuscation. Name obuscation use a feature of the PDF language
|
||||
that allows a character in a name (like /JavaScript) to be replaced
|
||||
with its hexcode. Example: /#4AavaScript
|
||||
http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/
|
||||
|
||||
It's something that's used in-the-wild.
|
||||
|
||||
I've updated your regex to support name obfuscation. The JavaScript
|
||||
itself is now captured in group 13.
|
||||
|
||||
\/S\s*\/(J|#4A|#4a)(a|#61)(v|#76)(a|#61)(S|#53)(c|#63)(r|#72)(i|#69)(p|#70)(t|#74)\s*\/(J|#4A|#4a)(S|#53)
|
||||
\((.+?)>>
|
||||
|
||||
2.
|
||||
---------------
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
import re
|
||||
import zlib
|
||||
|
||||
SAMPLE1 = 'malware1.pdf.vir'
|
||||
SAMPLE2 = 'heapspray-simpler-calc.pdf.vir'
|
||||
|
||||
try:
|
||||
import idaapi
|
||||
import idc
|
||||
import ida_idp
|
||||
ida = True
|
||||
except:
|
||||
ida = False
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Tries to find shellcode inside JavaScript statements
|
||||
# The seach algorithm is simple: it searchs for anything between unescape()
|
||||
# if it encounters %u or %x it correctly decodes them to characters
|
||||
def extract_shellcode(lines):
|
||||
p = 0
|
||||
shellcode = [] # accumulate shellcode
|
||||
while True:
|
||||
p = lines.find(b'unescape("', p)
|
||||
if p == -1:
|
||||
break
|
||||
e = lines.find(b')', p)
|
||||
if e == -1:
|
||||
break
|
||||
expr = lines[p+9:e]
|
||||
data = []
|
||||
def put_byte(b):
|
||||
if sys.version_info.major >= 3:
|
||||
data.append(b)
|
||||
else:
|
||||
data.append(chr(b))
|
||||
|
||||
for i in range(0, len(expr)):
|
||||
if expr[i:i+2] == b"%u":
|
||||
i += 2
|
||||
put_byte(int(expr[i+2:i+4], 16))
|
||||
put_byte(int(expr[i:i+2], 16))
|
||||
i += 4
|
||||
elif expr[i] == b"%":
|
||||
i += 1
|
||||
put_byte(int(expr[i:i+2], 16))
|
||||
i += 2
|
||||
# advance the match pos
|
||||
p += 8
|
||||
if sys.version_info.major >= 3:
|
||||
shellcode.append(bytes(data))
|
||||
else:
|
||||
shellcode.append("".join(data))
|
||||
|
||||
# That's it
|
||||
return shellcode
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Given a PDF object id and version, we return the object declaration
|
||||
def find_obj(buf, id, ver):
|
||||
stream = re.search(b'%d %d obj(.*?)endobj' % (id, ver), buf, re.MULTILINE | re.DOTALL)
|
||||
if not stream:
|
||||
return None
|
||||
return buf[stream.start(1):stream.end(1)]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Find JavaScript objects and extract the referenced script object id/ver
|
||||
def find_js_ref_streams(buf):
|
||||
o = []
|
||||
js_ref_streams = re.finditer(r'\/S\s*\/JavaScript\/JS (\d+) (\d+) R'.encode("UTF-8"), buf)
|
||||
for g in js_ref_streams:
|
||||
id = int(g.group(1))
|
||||
ver = int(g.group(2))
|
||||
o.append([id, ver])
|
||||
return o
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Find JavaScript objects and extract the embedded script
|
||||
def find_embedded_js(buf):
|
||||
r = re.finditer(r'\/S\s*\/JavaScript\s*\/JS \((.+?)>>'.encode("UTF-8"), buf, re.MULTILINE | re.DOTALL)
|
||||
if not r:
|
||||
return None
|
||||
|
||||
ret = []
|
||||
for js in r:
|
||||
p = buf.rfind(b'obj', 0, js.start(1))
|
||||
if p == -1:
|
||||
return None
|
||||
|
||||
scs = extract_shellcode(js.group(1))
|
||||
if not scs:
|
||||
return None
|
||||
|
||||
t = buf[p - min(20, len(buf)): p + 3]
|
||||
obj = re.search('(\d+) (\d+) obj'.encode("UTF-8"), t)
|
||||
if not obj:
|
||||
id, ver = 0
|
||||
else:
|
||||
id = int(obj.group(1))
|
||||
ver = int(obj.group(2))
|
||||
n = 0
|
||||
for sc in scs:
|
||||
n += 1
|
||||
ret.append([id, ver, n, sc])
|
||||
return ret
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Given a gzipped stream object, it returns the decompressed contents
|
||||
def decompress_stream(buf):
|
||||
if buf.find(b'Filter[/FlateDecode]') == -1:
|
||||
return None
|
||||
m = re.search(b'stream\s*(.+?)\s*endstream', buf, re.DOTALL | re.MULTILINE)
|
||||
if not m:
|
||||
return None
|
||||
# Decompress and return
|
||||
return zlib.decompress(m.group(1))
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def read_whole_file(li):
|
||||
li.seek(0)
|
||||
return li.read(li.size())
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def extract_pdf_shellcode(buf):
|
||||
ret = []
|
||||
|
||||
# find all JS stream references
|
||||
r = find_js_ref_streams(buf)
|
||||
for id, ver in r:
|
||||
# extract the JS stream object
|
||||
obj = find_obj(buf, id, ver)
|
||||
|
||||
# decode the stream
|
||||
stream = decompress_stream(obj)
|
||||
|
||||
# extract shell code
|
||||
scs = extract_shellcode(stream)
|
||||
i = 0
|
||||
for sc in scs:
|
||||
i += 1
|
||||
ret.append([id, ver, i, sc])
|
||||
|
||||
# find all embedded JS
|
||||
r = find_embedded_js(buf)
|
||||
if r:
|
||||
ret.extend(r)
|
||||
|
||||
return ret
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def accept_file(li, filename):
|
||||
"""
|
||||
Check if the file is of supported format
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param filename: name of the file, if it is an archive member name then the actual file doesn't exist
|
||||
@return: 0 - no more supported formats
|
||||
string "name" - format name to display in the chooser dialog
|
||||
dictionary { 'format': "name", 'options': integer }
|
||||
options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000)
|
||||
to indicate preferred format
|
||||
"""
|
||||
|
||||
# we support only one format per file
|
||||
li.seek(0)
|
||||
if li.read(5) != b'%PDF-':
|
||||
return 0
|
||||
|
||||
buf = read_whole_file(li)
|
||||
r = extract_pdf_shellcode(buf)
|
||||
if not r:
|
||||
return 0
|
||||
|
||||
return {'format': 'PDF with shellcode', 'processor': 'metapc'}
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def load_file(li, neflags, format):
|
||||
|
||||
"""
|
||||
Load the file into database
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param neflags: options selected by the user, see loader.hpp
|
||||
@return: 0-failure, 1-ok
|
||||
"""
|
||||
|
||||
# Select the PC processor module
|
||||
idaapi.set_processor_type("metapc", ida_idp.SETPROC_LOADER)
|
||||
|
||||
buf = read_whole_file(li)
|
||||
r = extract_pdf_shellcode(buf)
|
||||
if not r:
|
||||
return 0
|
||||
|
||||
# Load all shellcode into different segments
|
||||
start = 0x10000
|
||||
seg = idaapi.segment_t()
|
||||
for id, ver, n, sc in r:
|
||||
size = len(sc)
|
||||
end = start + size
|
||||
|
||||
# Create the segment
|
||||
seg.start_ea = start
|
||||
seg.end_ea = end
|
||||
seg.bitness = 1 # 32-bit
|
||||
idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0)
|
||||
|
||||
# Copy the bytes
|
||||
idaapi.mem2base(sc, start, end)
|
||||
|
||||
# Mark for analysis
|
||||
idc.AutoMark(start, idc.AU_CODE)
|
||||
|
||||
# Compute next loading address
|
||||
start = ((end // 0x1000) + 1) * 0x1000
|
||||
|
||||
# Select the bochs debugger
|
||||
idc.load_debugger("bochs", 0)
|
||||
|
||||
return 1
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def test1(sample = SAMPLE1):
|
||||
# open the file
|
||||
f = file(sample, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
# find all JS stream references
|
||||
r = find_js_ref_streams(buf)
|
||||
if not r:
|
||||
return
|
||||
|
||||
for id, ver in r:
|
||||
obj = find_obj(buf, id, ver)
|
||||
|
||||
# extract the JS stream object
|
||||
f = file('obj_%d_%d.bin' % (id, ver), 'wb')
|
||||
f.write(obj)
|
||||
f.close()
|
||||
|
||||
# decode the stream
|
||||
stream = decompress_stream(obj)
|
||||
f = file('dec_%d_%d.bin' % (id, ver), 'wb')
|
||||
f.write(stream)
|
||||
f.close()
|
||||
|
||||
# extract shell code
|
||||
scs = extract_shellcode(stream)
|
||||
i = 0
|
||||
for sc in scs:
|
||||
i += 1
|
||||
f = file('sh_%d_%d_%d.bin' % (id, ver, i), 'wb')
|
||||
f.write(sc)
|
||||
f.close()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def test2(sample = SAMPLE1):
|
||||
# open the file
|
||||
f = file(sample, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
|
||||
r = extract_pdf_shellcode(buf)
|
||||
for id, ver, n, sc in r:
|
||||
print("sc %d.%d[%d]=%d" % (id, ver, n, len(sc)))
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def test3(sample = SAMPLE2):
|
||||
# open the file
|
||||
f = file(sample, 'rb')
|
||||
buf = f.read()
|
||||
f.close()
|
||||
t = find_embedded_js(buf)
|
||||
print(t)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def main():
|
||||
test1(SAMPLE1)
|
||||
|
||||
if not ida:
|
||||
main()
|
||||
218
idasdk76/ldr/script_ldrs/uimage.py
Normal file
218
idasdk76/ldr/script_ldrs/uimage.py
Normal file
@@ -0,0 +1,218 @@
|
||||
# a file loader for U-Boot "uImage" flash images
|
||||
# Copyright (c) 2011-2021 Hex-Rays
|
||||
# ALL RIGHTS RESERVED.
|
||||
|
||||
import idaapi
|
||||
import idc
|
||||
import zlib
|
||||
import ida_idp
|
||||
import ida_typeinf
|
||||
|
||||
IH_TYPE_INVALID = 0 # /* Invalid Image */
|
||||
IH_TYPE_STANDALONE = 1 # /* Standalone Program */
|
||||
IH_TYPE_KERNEL = 2 # /* OS Kernel Image */
|
||||
IH_TYPE_RAMDISK = 3 # /* RAMDisk Image */
|
||||
IH_TYPE_MULTI = 4 # /* Multi-File Image */
|
||||
IH_TYPE_FIRMWARE = 5 # /* Firmware Image */
|
||||
IH_TYPE_SCRIPT = 6 # /* Script file */
|
||||
IH_TYPE_FILESYSTEM = 7 # /* Filesystem Image (any type) */
|
||||
|
||||
ImageTypeNames = [ "Invalid", "Standalone Program", "OS Kernel", "RAMDisk",
|
||||
"Multi-File", "Firmware", "Script file", "Filesystem" ]
|
||||
|
||||
IH_ARCH_INVALID = 0 # /* Invalid CPU */
|
||||
IH_ARCH_ALPHA = 1 # /* Alpha */
|
||||
IH_ARCH_ARM = 2 # /* ARM */
|
||||
IH_ARCH_I386 = 3 # /* Intel x86 */
|
||||
IH_ARCH_IA64 = 4 # /* IA64 */
|
||||
IH_ARCH_MIPS = 5 # /* MIPS */
|
||||
IH_ARCH_MIPS64 = 6 # /* MIPS 64 Bit */
|
||||
IH_ARCH_PPC = 7 # /* PowerPC */
|
||||
IH_ARCH_S390 = 8 # /* IBM S390 */
|
||||
IH_ARCH_SH = 9 # /* SuperH */
|
||||
IH_ARCH_SPARC = 10 # /* Sparc */
|
||||
IH_ARCH_SPARC64 = 11 # /* Sparc 64 Bit */
|
||||
IH_ARCH_M68K = 12 # /* M68K */
|
||||
IH_ARCH_NIOS = 13 # /* Nios-32 */
|
||||
IH_ARCH_MICROBLAZE = 14 # /* MicroBlaze */
|
||||
IH_ARCH_NIOS2 = 15 # /* Nios-II */
|
||||
IH_ARCH_BLACKFIN = 16 # /* */
|
||||
IH_ARCH_AVR32 = 17 # /* */
|
||||
IH_ARCH_ST200 = 18 # /* */
|
||||
IH_ARCH_SANDBOX = 19 # /* */
|
||||
IH_ARCH_NDS32 = 20 # /* */
|
||||
IH_ARCH_OPENRISC = 21 # /* */
|
||||
IH_ARCH_ARM64 = 22 # /* */
|
||||
IH_ARCH_ARC = 23 # /* */
|
||||
|
||||
CPUNames = [ "Invalid", "Alpha", "ARM", "x86", "IA64", "MIPS", "MIPS64", "PowerPC",
|
||||
"IBM S390", "SuperH", "Sparc", "Sparc64", "M68K", "Nios-32", "MicroBlaze", "Nios-II",
|
||||
"Blackfin", "AVR32", "ST200","Sandbox","NDS32", "OpenRISC", "ARM64", "ARC" ]
|
||||
|
||||
IDACPUNames = { IH_ARCH_ALPHA: "alphab",
|
||||
IH_ARCH_ARM:"ARM",
|
||||
IH_ARCH_I386: "metapc",
|
||||
IH_ARCH_IA64: "ia64b",
|
||||
IH_ARCH_MIPS:"mipsl",
|
||||
IH_ARCH_MIPS64:"mipsl",
|
||||
IH_ARCH_PPC: "ppc",
|
||||
IH_ARCH_SH: "SH4",
|
||||
IH_ARCH_SPARC: "sparcb",
|
||||
IH_ARCH_SPARC64:"sparcb",
|
||||
IH_ARCH_M68K:"68K",
|
||||
IH_ARCH_ARM64:"ARM",
|
||||
IH_ARCH_ARC: "arcmpct" }
|
||||
|
||||
IDAABINames = { IH_ARCH_MIPS:"n32",
|
||||
IH_ARCH_MIPS64:"n64" }
|
||||
|
||||
IH_COMP_NONE = 0 # /* No Compression Used */
|
||||
IH_COMP_GZIP = 1 # /* gzip Compression Used */
|
||||
IH_COMP_BZIP2 = 2 # /* bzip2 Compression Used */
|
||||
IH_COMP_LZMA = 3 # /* lzma Compression Used */
|
||||
IH_COMP_LZO = 4 # /* lzo Compression Used */
|
||||
CompTypeNames = [ "", "gzip", "bzip2", "lzma", "lzo" ]
|
||||
|
||||
IH_MAGIC = 0x27051956 # Image Magic Number
|
||||
IH_NMLEN = 32 # Image Name Length
|
||||
|
||||
import ctypes
|
||||
|
||||
uint8_t = ctypes.c_byte
|
||||
uint32_t = ctypes.c_uint
|
||||
|
||||
class image_header(ctypes.BigEndianStructure):
|
||||
_fields_ = [
|
||||
("ih_magic", uint32_t), # Image Header Magic Number
|
||||
("ih_hcrc", uint32_t), # Image Header CRC Checksum
|
||||
("ih_time", uint32_t), # Image Creation Timestamp
|
||||
("ih_size", uint32_t), # Image Data Size
|
||||
("ih_load", uint32_t), # Data Load Address
|
||||
("ih_ep", uint32_t), # Entry Point Address
|
||||
("ih_dcrc", uint32_t), # Image Data CRC Checksum
|
||||
("ih_os", uint8_t), # Operating System
|
||||
("ih_arch", uint8_t), # CPU architecture
|
||||
("ih_type", uint8_t), # Image Type
|
||||
("ih_comp", uint8_t), # Compression Type
|
||||
("ih_name", uint8_t * IH_NMLEN), # Image Name
|
||||
]
|
||||
RomFormatName = "U-Boot image"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def dwordAt(li, off):
|
||||
li.seek(off)
|
||||
s = li.read(4)
|
||||
if len(s) < 4:
|
||||
return 0
|
||||
return struct.unpack('<I', s)[0]
|
||||
|
||||
def read_struct(li, struct):
|
||||
s = struct()
|
||||
s.ih_magic = 0
|
||||
slen = ctypes.sizeof(s)
|
||||
if li.size() >= slen:
|
||||
bytes = li.read(slen)
|
||||
fit = min(len(bytes), slen)
|
||||
ctypes.memmove(ctypes.addressof(s), bytes, fit)
|
||||
return s
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def accept_file(li, filename):
|
||||
"""
|
||||
Check if the file is of supported format
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param filename: name of the file, if it is an archive member name then the actual file doesn't exist
|
||||
@return: 0 - no more supported formats
|
||||
string "name" - format name to display in the chooser dialog
|
||||
dictionary { 'format': "name", 'options': integer }
|
||||
options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000)
|
||||
to indicate preferred format
|
||||
"""
|
||||
|
||||
header = read_struct(li, image_header)
|
||||
# check the signature
|
||||
if header.ih_magic == IH_MAGIC:
|
||||
# accept the file
|
||||
t = header.ih_type
|
||||
c = header.ih_arch
|
||||
if t >= len(ImageTypeNames):
|
||||
t = "unknown type(%d)" % t
|
||||
else:
|
||||
t = ImageTypeNames[t]
|
||||
|
||||
if c >= len(CPUNames):
|
||||
cname = "unknown CPU(%d)" % c
|
||||
else:
|
||||
cname = CPUNames[c]
|
||||
|
||||
fmt = "%s (%s for %s)" % (RomFormatName, t, cname)
|
||||
comp = header.ih_comp
|
||||
if comp != IH_COMP_NONE:
|
||||
if comp >= len (CompTypeNames):
|
||||
cmpname = "unknown compression(%d)"
|
||||
else:
|
||||
cmpname = "%s compressed" % CompTypeNames[comp]
|
||||
fmt += " [%s]" % cmpname
|
||||
|
||||
proc = ''
|
||||
if c in IDACPUNames:
|
||||
proc = IDACPUNames[c]
|
||||
|
||||
return {'format': fmt, 'processor': proc}
|
||||
|
||||
# unrecognized format
|
||||
return 0
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def load_file(li, neflags, format):
|
||||
|
||||
"""
|
||||
Load the file into database
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param neflags: options selected by the user, see loader.hpp
|
||||
@return: 0-failure, 1-ok
|
||||
"""
|
||||
|
||||
if format.startswith(RomFormatName):
|
||||
li.seek(0)
|
||||
header = read_struct(li, image_header)
|
||||
c = header.ih_arch
|
||||
cname = IDACPUNames.get(c)
|
||||
if not cname:
|
||||
idc.warning("Unsupported CPU")
|
||||
#return
|
||||
|
||||
if not header.ih_comp in (IH_COMP_NONE, IH_COMP_GZIP):
|
||||
idc.warning("Can only handle uncompressed or gzip-compressed images")
|
||||
return
|
||||
|
||||
if cname:
|
||||
idaapi.set_processor_type(cname, ida_idp.SETPROC_LOADER)
|
||||
|
||||
idc.AddSeg(header.ih_load, header.ih_load + header.ih_size, 0, 1, idaapi.saRelPara, idaapi.scPub)
|
||||
|
||||
# copy bytes to the database
|
||||
|
||||
if header.ih_comp == IH_COMP_NONE:
|
||||
li.file2base(ctypes.sizeof(header), header.ih_load, header.ih_load + header.ih_size, 0)
|
||||
else:
|
||||
cdata = li.read(header.ih_size)
|
||||
d = zlib.decompressobj(zlib.MAX_WBITS|32)
|
||||
udata = d.decompress(cdata)
|
||||
udata += d.flush()
|
||||
# expand segment to fit uncompressed data
|
||||
idc.set_segment_bounds(header.ih_load, header.ih_load, header.ih_load+len(udata), idc.SEGMOD_KEEP)
|
||||
idaapi.put_bytes(header.ih_load, udata)
|
||||
|
||||
if cname == "ARM" and (header.ih_ep & 1) != 0:
|
||||
# Thumb entry point
|
||||
header.ih_ep -= 1
|
||||
split_sreg_range(header.ih_ep, "T", 1)
|
||||
idaapi.add_entry(header.ih_ep, header.ih_ep, "start", 1)
|
||||
aname = IDAABINames.get(header.ih_arch)
|
||||
if aname:
|
||||
ida_typeinf.set_abi_name(aname)
|
||||
print("Load OK")
|
||||
return 1
|
||||
119
idasdk76/ldr/script_ldrs/wince.py
Normal file
119
idasdk76/ldr/script_ldrs/wince.py
Normal file
@@ -0,0 +1,119 @@
|
||||
# an example of a file loader in Python
|
||||
# The scripting loader must define at least two functions: accept_file and load_file
|
||||
# other optional functions are: save_file, move_segm, ...
|
||||
#
|
||||
# see also loader.hpp
|
||||
|
||||
import idaapi
|
||||
import ida_idp
|
||||
import idc
|
||||
import struct
|
||||
|
||||
ROM_SIGNATURE_OFFSET = 64
|
||||
ROM_SIGNATURE = "ECEC"
|
||||
RomFormatName = "Windows CE ROM"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def dwordAt(li, off):
|
||||
li.seek(off)
|
||||
s = li.read(4)
|
||||
if len(s) < 4:
|
||||
return 0
|
||||
return struct.unpack('<I', s)[0]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def guess_processor(li):
|
||||
jump = dwordAt(li, 0)
|
||||
if jump & 0xFF000000 == 0xEA000000: # looks like an ARM branch?
|
||||
return "arm"
|
||||
else:
|
||||
return "metapc"
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def accept_file(li, filename):
|
||||
"""
|
||||
Check if the file is of supported format
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param filename: name of the file, if it is an archive member name then the actual file doesn't exist
|
||||
@return: 0 - no more supported formats
|
||||
string "name" - format name to display in the chooser dialog
|
||||
dictionary { 'format': "name", 'options': integer }
|
||||
options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000)
|
||||
to indicate preferred format
|
||||
"""
|
||||
|
||||
# check the CECE signature
|
||||
li.seek(ROM_SIGNATURE_OFFSET)
|
||||
if li.read(4) == ROM_SIGNATURE:
|
||||
# accept the file
|
||||
proc = guess_processor(li)
|
||||
return {'format': RomFormatName, 'processor': proc}
|
||||
|
||||
# unrecognized format
|
||||
return 0
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def load_file(li, neflags, format):
|
||||
|
||||
"""
|
||||
Load the file into database
|
||||
|
||||
@param li: a file-like object which can be used to access the input data
|
||||
@param neflags: options selected by the user, see loader.hpp
|
||||
@return: 0-failure, 1-ok
|
||||
"""
|
||||
|
||||
if format == RomFormatName:
|
||||
proc = guess_processor(li)
|
||||
idaapi.set_processor_type(proc, ida_idp.SETPROC_LOADER)
|
||||
|
||||
li.seek(0, idaapi.SEEK_END)
|
||||
size = li.tell()
|
||||
|
||||
#next dword after signature is a pointer to ROMHDR
|
||||
romhdr = dwordAt(li, ROM_SIGNATURE_OFFSET + 4)
|
||||
|
||||
# let's try to find such imagebase that potential ROMHDR's "physfirst" value matches it
|
||||
imgbase = (romhdr-size) & ~0xfff
|
||||
bases = []
|
||||
maxbase = 0
|
||||
while imgbase < romhdr+8:
|
||||
physfirst = dwordAt(li, romhdr - imgbase + 8)
|
||||
if physfirst == imgbase:
|
||||
bases.append(imgbase)
|
||||
imgbase += 0x1000
|
||||
|
||||
if len(bases) == 1:
|
||||
start = bases[0]
|
||||
elif len(bases) > 1:
|
||||
print("warning: several potential imagebases detemined: " + ", ".join("%08X"%i for i in bases))
|
||||
start = bases[-1]
|
||||
else:
|
||||
warning("Unable to determine load image base.")
|
||||
start = 0x80000000
|
||||
print("Using imagebase %08X" % start)
|
||||
|
||||
physlast = dwordAt(li, romhdr - start + 12)
|
||||
if physlast <= start:
|
||||
warning("Internal error")
|
||||
return 0
|
||||
size = physlast - start
|
||||
|
||||
idc.AddSeg(start, start+size, 0, 1, idaapi.saRelPara, idaapi.scPub)
|
||||
|
||||
# copy bytes to the database
|
||||
li.seek(0)
|
||||
li.file2base(0, start, start+size, 0)
|
||||
|
||||
idaapi.add_entry(start, start, "start", 1)
|
||||
print("Load OK")
|
||||
return 1
|
||||
|
||||
idc.warning("Unknown format name: '%s'" % format)
|
||||
return 0
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def move_segm(frm, to, sz, fileformatname):
|
||||
idc.warning("move_segm(from=%s, to=%s, sz=%d, formatname=%s" % (hex(frm), hex(to), sz, fileformatname))
|
||||
return 0
|
||||
883
idasdk76/ldr/snes/addr.cpp
Normal file
883
idasdk76/ldr/snes/addr.cpp
Normal file
@@ -0,0 +1,883 @@
|
||||
|
||||
// This file is included from the loader module and the processor module
|
||||
|
||||
#include "super-famicom.hpp"
|
||||
|
||||
class snes_addr_t
|
||||
{
|
||||
SuperFamicomCartridge g_cartridge;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ea_t xlat_system(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// WRAM
|
||||
if ( bank >= 0x7e && bank <= 0x7f )
|
||||
return address;
|
||||
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr <= 0x1fff ) // Low RAM
|
||||
return 0x7e0000 + addr;
|
||||
else if ( addr >= 0x2100 && addr <= 0x213f ) // PPU registers
|
||||
return addr;
|
||||
else if ( addr >= 0x2140 && addr <= 0x2183 ) // CPU registers
|
||||
return addr;
|
||||
else if ( addr >= 0x4016 && addr <= 0x4017 ) // CPU registers
|
||||
return addr;
|
||||
else if ( addr >= 0x4200 && addr <= 0x421f ) // CPU registers
|
||||
return addr;
|
||||
else if ( addr >= 0x4300 && addr <= 0x437f ) // CPU registers
|
||||
return addr;
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// hitachidsp model=HG51B169 frequency=20000000
|
||||
// rom id=program name=program.rom size=hex(rom_size)
|
||||
// rom id=data name=cx4.data.rom size=0xc00
|
||||
// ram id=data size=0xc00
|
||||
// map id=io address=00-3f,80-bf:6000-7fff
|
||||
// map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000
|
||||
// map id=ram address=70-77:0000-7fff
|
||||
ea_t xlat_cx4(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0
|
||||
&& bank >= 0x70
|
||||
&& bank <= 0x77
|
||||
&& addr <= 0x7fff )
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
// mirror 00-7d => 80-fd (excluding SRAM)
|
||||
if ( bank <= 0x7d )
|
||||
{
|
||||
address += 0x800000;
|
||||
bank += 0x80;
|
||||
}
|
||||
|
||||
if ( bank <= 0xbf )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM
|
||||
return address;
|
||||
}
|
||||
else if ( addr >= 0x6000 )
|
||||
{
|
||||
// CX4 registers
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// spc7110
|
||||
// rom id=program name=program.rom size=0x100000
|
||||
// rom id=data name=data.rom size=hex(rom_size - 0x100000)
|
||||
// ram name=save.ram size=0x", hex(ram_size)
|
||||
// map id=io address=00-3f,80-bf:4800-483f
|
||||
// map id=io address=50:0000-ffff
|
||||
// map id=rom address=00-3f,80-bf:8000-ffff
|
||||
// map id=rom address=c0-ff:0000-ffff
|
||||
// map id=ram address=00-3f,80-bf:6000-7fff mask=0xe000
|
||||
ea_t xlat_spc7110(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0x1f) << 13) + (addr - 0x6000)) & ram_mask;
|
||||
uint32 res = ((ram_offset >> 13) << 16) + (0x6000 + (ram_offset & 0x1fff));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decompressed ROM
|
||||
if ( bank >= 0x50 && bank <= 0x5f )
|
||||
return address;
|
||||
|
||||
// mirror 00-7d => 80-fd (excluding SRAM, Decompressed ROM)
|
||||
if ( bank <= 0x7d )
|
||||
{
|
||||
address += 0x800000;
|
||||
bank += 0x80;
|
||||
}
|
||||
|
||||
if ( bank >= 0xc0 )
|
||||
{
|
||||
// ROM (HiROM layout)
|
||||
return address;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (LoROM-like layout)
|
||||
return ((0xc0 + (bank & 0x3f)) << 16) + addr;
|
||||
}
|
||||
else if ( addr >= 0x4800 && addr <= 0x483f )
|
||||
{
|
||||
// SPC7110 registers
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// sdd1
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram name=save.ram size=hex(ram_size)
|
||||
// map id=io address=00-3f,80-bf:4800-4807
|
||||
// map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000
|
||||
// map id=rom address=c0-ff:0000-ffff
|
||||
// map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000
|
||||
// map id=ram address=70-7f:0000-7fff
|
||||
ea_t xlat_sdd1(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( bank >= 0x70 && bank <= 0x7d )
|
||||
{
|
||||
if ( addr <= 0x7fff )
|
||||
{
|
||||
// LoROM SRAM style
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0xf) << 15) + (addr & 0x7fff)) & ram_mask;
|
||||
uint32 res = ((0x70 + (ram_offset >> 15)) << 16) + (ram_offset & 0x7fff);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else if ( ( bank >= 0x20 && bank <= 0x3f ) || ( bank >= 0xa0 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
// HiROM SRAM style (not usually used?)
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0x1f) << 13) + (addr - 0x6000)) & ram_mask;
|
||||
uint32 res = ((0x20 + (ram_offset >> 13)) << 16) + (0x6000 + (ram_offset & 0x1fff));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (LoROM style)
|
||||
return ((bank | 0x80) << 16) + addr;
|
||||
}
|
||||
else if ( addr >= 0x4800 && addr <= 0x4807 )
|
||||
{
|
||||
// S-DD1 registers
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
else if ( bank >= 0xc0 )
|
||||
{
|
||||
// ROM (HiROM style)
|
||||
return address;
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram name=save.ram size=hex(ram_size)
|
||||
// map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000
|
||||
// map id=ram address=70-7f,f0-ff:[0000-7fff|0000-ffff]
|
||||
ea_t xlat_lorom(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
bool preserve_rom_mirror = (g_cartridge.rom_size > 0x200000) || (g_cartridge.ram_size > 32 * 1024);
|
||||
|
||||
if ( ( bank >= 0x70 && bank <= 0x7d ) || bank >= 0xf0 )
|
||||
{
|
||||
if ( addr <= 0x7fff || !preserve_rom_mirror )
|
||||
{
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0xf) << 15) + (addr & 0x7fff)) & ram_mask;
|
||||
uint32 ea = ((0x70 + (ram_offset >> 15)) << 16) + (ram_offset & 0x7fff);
|
||||
if ( bank >= 0xfe )
|
||||
ea += 0x800000;
|
||||
return ea;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mirror 00-7d => 80-fd (excluding SRAM)
|
||||
if ( bank <= 0x7d )
|
||||
{
|
||||
address += 0x800000;
|
||||
bank += 0x80;
|
||||
}
|
||||
|
||||
// ROM
|
||||
if ( bank <= 0xbf )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram name=save.ram size=hex(ram_size)
|
||||
// map id=rom address=00-3f,80-bf:8000-ffff
|
||||
// map id=rom address=40-7f,c0-ff:0000-ffff
|
||||
// map id=ram address=10-3f,90-bf:6000-7fff mask=0xe000
|
||||
ea_t xlat_hirom(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( ( bank >= 0x10 && bank <= 0x3f ) || ( bank >= 0x90 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
// Typically, HiROM SRAM starts from $20:0000, but there are exceptions.
|
||||
// Example: Donkey Kong Country 2 (reads $B0:6000 for 2 kilobytes SRAM)
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0x1f) << 13) + (addr - 0x6000)) & ram_mask;
|
||||
uint32 res = ((0x20 + (ram_offset >> 13)) << 16) + (0x6000 + (ram_offset & 0x1fff));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mirror 00-7d => 80-fd (excluding SRAM)
|
||||
if ( bank <= 0x7d )
|
||||
{
|
||||
address += 0x800000;
|
||||
bank += 0x80;
|
||||
}
|
||||
|
||||
if ( bank >= 0xc0 )
|
||||
{
|
||||
// ROM (HiROM layout)
|
||||
return address;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (LoROM-like layout)
|
||||
return ((0xc0 + (bank & 0x3f)) << 16) + addr;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram name=save.ram size=hex(ram_size)
|
||||
// map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000
|
||||
// map id=rom address=40-7f:0000-ffff
|
||||
// map id=ram address=20-3f,a0-bf:6000-7fff
|
||||
// map id=ram address=70-7f:0000-7fff
|
||||
ea_t xlat_exlorom(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( bank >= 0x70 && bank <= 0x7d )
|
||||
{
|
||||
if ( addr <= 0x7fff )
|
||||
{
|
||||
// LoROM SRAM style
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0xf) << 15) + (addr & 0x7fff)) & ram_mask;
|
||||
uint32 res = ((0x70 + (ram_offset >> 15)) << 16) + (ram_offset & 0x7fff);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else if ( ( bank >= 0x20 && bank <= 0x3f ) || ( bank >= 0xa0 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
// HiROM SRAM style (not usually used?)
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0x1f) << 13) + (addr - 0x6000)) & ram_mask;
|
||||
uint32 res = ((0x20 + (ram_offset >> 13)) << 16) + (0x6000 + (ram_offset & 0x1fff));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (LoROM style)
|
||||
return ((bank | 0x80) << 16) + addr;
|
||||
}
|
||||
}
|
||||
else if ( bank <= 0x7f )
|
||||
{
|
||||
// ROM (HiROM style)
|
||||
return address;
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram name=save.ram size=hex(ram_size)
|
||||
// map id=rom address=00-3f:8000-ffff base=0x400000
|
||||
// map id=rom address=40-7f:0000-ffff base=0x400000
|
||||
// map id=rom address=80-bf:8000-ffff mask=0xc00000
|
||||
// map id=rom address=c0-ff:0000-ffff mask=0xc00000
|
||||
// map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000
|
||||
// map id=ram address=70-7f:[0000-7fff|0000-ffff]
|
||||
ea_t xlat_exhirom(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SRAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( ( bank >= 0x20 && bank <= 0x3f ) || ( bank >= 0xa0 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
// HiROM SRAM style
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0x1f) << 13) + (addr - 0x6000)) & ram_mask;
|
||||
uint32 res = ((0x20 + (ram_offset >> 13)) << 16) + (0x6000 + (ram_offset & 0x1fff));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else if ( bank >= 0x70 && bank <= 0x7d )
|
||||
{
|
||||
bool preserve_rom_mirror = (g_cartridge.rom_size > 0x200000) || (g_cartridge.ram_size > 32 * 1024);
|
||||
|
||||
if ( addr <= 0x7fff || !preserve_rom_mirror )
|
||||
{
|
||||
// LoROM SRAM style (not usually used?)
|
||||
uint32 ram_mask = g_cartridge.ram_size - 1;
|
||||
uint32 ram_offset = (((bank & 0xf) << 15) + (addr & 0x7fff)) & ram_mask;
|
||||
uint32 res = ((0x70 + (ram_offset >> 15)) << 16) + (ram_offset & 0x7fff);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bank >= 0xc0 )
|
||||
{
|
||||
// ROM
|
||||
return address;
|
||||
}
|
||||
else if ( bank >= 0x80 )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (mirror to c0-ff)
|
||||
return ((bank + 0x40) << 16) + addr;
|
||||
}
|
||||
}
|
||||
else if ( bank >= 0x40 )
|
||||
{
|
||||
// Extended ROM
|
||||
return address;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// Extended ROM (mirror to 40-7f)
|
||||
return ((bank + 0x40) << 16) + addr;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// superfx revision=4
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram name=save.ram size=hex(ram_size)
|
||||
// map id=io address=00-3f,80-bf:3000-34ff
|
||||
// map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000
|
||||
// map id=rom address=40-5f,c0-df:0000-ffff
|
||||
// map id=ram address=00-3f,80-bf:6000-7fff size=0x2000
|
||||
// map id=ram address=70-71,f0-f1:0000-ffff
|
||||
ea_t xlat_superfxrom(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// SuperFX RAM
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
// 2kB Game Work RAM
|
||||
return (0x00 << 16) + addr;
|
||||
}
|
||||
}
|
||||
else if ( ( bank >= 0x70 && bank <= 0x7f ) || ( bank >= 0xf0 && bank <= 0xf1 ) )
|
||||
{
|
||||
// 128kB SRAM address space
|
||||
return ( ( bank & ~0x80 ) << 16 ) + addr;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( bank >= 0x40 && bank <= 0x5f ) || ( bank >= 0xc0 && bank <= 0xdf ) )
|
||||
{
|
||||
// ROM (HiROM layout)
|
||||
return address;
|
||||
}
|
||||
else if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (LoROM layout)
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// sa1
|
||||
// rom name=program.rom size=hex(rom_size)
|
||||
// ram id=bitmap name=save.ram size=hex(ram_size)
|
||||
// ram id=internal size=0x800
|
||||
// map id=io address=00-3f,80-bf:2200-23ff
|
||||
// map id=rom address=00-3f,80-bf:8000-ffff
|
||||
// map id=rom address=c0-ff:0000-ffff
|
||||
// map id=bwram address=00-3f,80-bf:6000-7fff
|
||||
// map id=bwram address=40-4f:0000-ffff
|
||||
// map id=iram address=00-3f,80-bf:3000-37ff
|
||||
ea_t xlat_sa1rom(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
// mirror 80-bf => 00-3f
|
||||
if ( bank >= 0x80 && bank <= 0xbf )
|
||||
{
|
||||
address -= 0x800000;
|
||||
bank -= 0x80;
|
||||
}
|
||||
|
||||
// SA1 BWRAM (SRAM)
|
||||
if ( g_cartridge.ram_size != 0 )
|
||||
{
|
||||
if ( bank <= 0x3f )
|
||||
{
|
||||
if ( addr >= 0x6000 && addr <= 0x7fff )
|
||||
{
|
||||
// 8 kilobytes RAM (shared with 40:0000-1fff)
|
||||
uint32 ram_offset = (addr & 0x7fff) - 0x6000;
|
||||
return (0x40 << 16) + ram_offset;
|
||||
}
|
||||
}
|
||||
else if ( bank <= 0x4f )
|
||||
{
|
||||
// 128 kB address space, redirects to banks 40-41
|
||||
return ((bank & ~0xe) << 16) + addr;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bank >= 0xc0 )
|
||||
{
|
||||
// ROM (HiROM layout)
|
||||
return address;
|
||||
}
|
||||
else if ( bank <= 0x3f )
|
||||
{
|
||||
if ( addr >= 0x8000 )
|
||||
{
|
||||
// ROM (LoROM layout)
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: SA1 Missing Memory Map
|
||||
// 00-3f|80-bf:0000-07ff IWRAM (SA1 side)
|
||||
// 60-6f:0000-ffff BWRAM Bitmap (SA1 side)
|
||||
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// sharprtc
|
||||
// ram name=rtc.ram size=0x10
|
||||
// map id=io address=00-3f,80-bf:2800-2801
|
||||
ea_t xlat_sharprtc(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x2800 && addr <= 0x2801 )
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// epsonrtc
|
||||
// ram name=rtc.ram size=0x10
|
||||
// map id=io address=00-3f,80-bf:4840-4842
|
||||
ea_t xlat_epsonrtc(ea_t address, bool & dispatched)
|
||||
{
|
||||
uint16 addr = address & 0xffff;
|
||||
uint8 bank = (address >> 16) & 0xff;
|
||||
|
||||
dispatched = true;
|
||||
|
||||
if ( bank <= 0x3f || ( bank >= 0x80 && bank <= 0xbf ) )
|
||||
{
|
||||
if ( addr >= 0x4840 && addr <= 0x4842 )
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
|
||||
dispatched = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// obc1
|
||||
// ram name=save.ram size=0x2000
|
||||
// map id=io address=00-3f,80-bf:6000-7fff
|
||||
ea_t xlat_obc1(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add OBC-1 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// necdsp model=uPD7725 frequency=8000000
|
||||
// rom id=program name=dsp1b.program.rom size=0x1800
|
||||
// rom id=data name=dsp1b.data.rom size=0x800
|
||||
// ram id=data size=0x200
|
||||
//
|
||||
// when DSP1LoROM1MB:
|
||||
// map id=io address=20-3f,a0-bf:8000-ffff select=0x4000
|
||||
//
|
||||
// when DSP1LoROM2MB:
|
||||
// map id=io address=60-6f,e0-ef:0000-7fff select=0x4000
|
||||
//
|
||||
// when DSP1HiROM:
|
||||
// map id=io address=00-1f,80-9f:6000-7fff select=0x1000
|
||||
ea_t xlat_dsp1(ea_t address, SuperFamicomCartridge::DSP1MemoryMapper /*dsp1_mapper*/, bool & dispatched)
|
||||
{
|
||||
// TODO: Add DSP-1 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// necdsp model=uPD7725 frequency=8000000
|
||||
// rom id=program name=dsp2.program.rom size=0x1800
|
||||
// rom id=data name=dsp2.data.rom size=0x800
|
||||
// ram id=data size=0x200
|
||||
// map id=io address=20-3f,a0-bf:8000-ffff select=0x4000
|
||||
ea_t xlat_dsp2(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add DSP-2 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// necdsp model=uPD7725 frequency=8000000
|
||||
// rom id=program name=dsp3.program.rom size=0x1800
|
||||
// rom id=data name=dsp3.data.rom size=0x800
|
||||
// ram id=data size=0x200
|
||||
// map id=io address=20-3f,a0-bf:8000-ffff select=0x4000
|
||||
ea_t xlat_dsp3(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add DSP-3 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// necdsp model=uPD7725 frequency=8000000
|
||||
// rom id=program name=dsp4.program.rom size=0x1800
|
||||
// rom id=data name=dsp4.data.rom size=0x800
|
||||
// ram id=data size=0x200
|
||||
// map id=io address=30-3f,b0-bf:8000-ffff select=0x4000
|
||||
ea_t xlat_dsp4(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add DSP-4 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// necdsp model=uPD96050 frequency=11000000
|
||||
// rom id=program name=st010.program.rom size=0xc000
|
||||
// rom id=data name=st010.data.rom size=0x1000
|
||||
// ram id=data name=save.ram size=0x1000
|
||||
// map id=io address=60-67,e0-e7:0000-3fff select=0x0001
|
||||
// map id=ram address=68-6f,e8-ef:0000-7fff
|
||||
ea_t xlat_st010(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add ST-010 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// necdsp model=uPD96050 frequency=15000000
|
||||
// rom id=program name=st011.program.rom size=0xc000
|
||||
// rom id=data name=st011.data.rom size=0x1000
|
||||
// ram id=data name=save.ram size=0x1000
|
||||
// map id=io address=60-67,e0-e7:0000-3fff select=0x0001
|
||||
// map id=ram address=68-6f,e8-ef:0000-7fff
|
||||
ea_t xlat_st011(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add ST-011 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// armdsp frequency=21477272
|
||||
// rom id=program name=st018.program.rom size=0x20000
|
||||
// rom id=data name=st018.data.rom size=0x8000
|
||||
// ram name=save.ram size=0x4000
|
||||
// map id=io address=00-3f,80-bf:3800-38ff
|
||||
ea_t xlat_st018(ea_t address, bool & dispatched)
|
||||
{
|
||||
// TODO: Add ST-018 address mapping
|
||||
dispatched = false;
|
||||
return address;
|
||||
}
|
||||
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
bool addr_init(const SuperFamicomCartridge & cartridge)
|
||||
{
|
||||
g_cartridge = cartridge;
|
||||
|
||||
switch ( g_cartridge.mapper )
|
||||
{
|
||||
case SuperFamicomCartridge::LoROM:
|
||||
case SuperFamicomCartridge::HiROM:
|
||||
case SuperFamicomCartridge::ExLoROM:
|
||||
case SuperFamicomCartridge::ExHiROM:
|
||||
case SuperFamicomCartridge::SuperFXROM:
|
||||
case SuperFamicomCartridge::SA1ROM:
|
||||
case SuperFamicomCartridge::SPC7110ROM:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ea_t xlat(ea_t address)
|
||||
{
|
||||
bool dispatched;
|
||||
ea_t remapped_address;
|
||||
|
||||
remapped_address = xlat_system(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
|
||||
if ( g_cartridge.has_cx4 )
|
||||
{
|
||||
remapped_address = xlat_cx4(address, dispatched);
|
||||
}
|
||||
else if ( g_cartridge.has_sdd1 )
|
||||
{
|
||||
remapped_address = xlat_sdd1(address, dispatched);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( g_cartridge.mapper )
|
||||
{
|
||||
case SuperFamicomCartridge::LoROM:
|
||||
remapped_address = xlat_lorom(address, dispatched);
|
||||
break;
|
||||
case SuperFamicomCartridge::HiROM:
|
||||
remapped_address = xlat_hirom(address, dispatched);
|
||||
break;
|
||||
case SuperFamicomCartridge::ExLoROM:
|
||||
remapped_address = xlat_exlorom(address, dispatched);
|
||||
break;
|
||||
case SuperFamicomCartridge::ExHiROM:
|
||||
remapped_address = xlat_exhirom(address, dispatched);
|
||||
break;
|
||||
case SuperFamicomCartridge::SuperFXROM:
|
||||
remapped_address = xlat_superfxrom(address, dispatched);
|
||||
break;
|
||||
case SuperFamicomCartridge::SA1ROM:
|
||||
remapped_address = xlat_sa1rom(address, dispatched);
|
||||
break;
|
||||
case SuperFamicomCartridge::SPC7110ROM:
|
||||
remapped_address = xlat_spc7110(address, dispatched);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
|
||||
if ( g_cartridge.has_sharprtc )
|
||||
{
|
||||
remapped_address = xlat_sharprtc(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_epsonrtc )
|
||||
{
|
||||
remapped_address = xlat_epsonrtc(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_obc1 )
|
||||
{
|
||||
remapped_address = xlat_obc1(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_dsp1 )
|
||||
{
|
||||
remapped_address = xlat_dsp1(address, g_cartridge.dsp1_mapper, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_dsp2 )
|
||||
{
|
||||
remapped_address = xlat_dsp2(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_dsp3 )
|
||||
{
|
||||
remapped_address = xlat_dsp3(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_dsp4 )
|
||||
{
|
||||
remapped_address = xlat_dsp4(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_st010 )
|
||||
{
|
||||
remapped_address = xlat_st010(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_st011 )
|
||||
{
|
||||
remapped_address = xlat_st011(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
if ( g_cartridge.has_st018 )
|
||||
{
|
||||
remapped_address = xlat_st018(address, dispatched);
|
||||
if ( dispatched )
|
||||
return remapped_address;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
};
|
||||
14
idasdk76/ldr/snes/makefile
Normal file
14
idasdk76/ldr/snes/makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
PROC=snes
|
||||
|
||||
include ../loader.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)snes$(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 ../idaldr.h addr.cpp snes.cpp \
|
||||
super-famicom.hpp
|
||||
716
idasdk76/ldr/snes/snes.cpp
Normal file
716
idasdk76/ldr/snes/snes.cpp
Normal file
@@ -0,0 +1,716 @@
|
||||
|
||||
#include "../idaldr.h"
|
||||
#include "addr.cpp"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_io_seg(ea_t start, ea_t end, const char *const name)
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = start;
|
||||
s.end_ea = end;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(start >> 4);
|
||||
if ( !add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", name);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_hwregs()
|
||||
{
|
||||
map_io_seg(0x2100, 0x2140, "ppu");
|
||||
map_io_seg(0x2140, 0x2144, "apu");
|
||||
map_io_seg(0x2180, 0x2184, "wramrw");
|
||||
map_io_seg(0x4016, 0x4018, "joypad");
|
||||
map_io_seg(0x4200, 0x4220, "misc");
|
||||
map_io_seg(0x4300, 0x4380, "dma");
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_wram()
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = 0x7e0000;
|
||||
s.end_ea = 0x800000;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), "wram");
|
||||
if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_lorom_sram_offset(uint32 ram_size, uint8 start_bank)
|
||||
{
|
||||
// Usually, the lower half of bank (0x8000 bytes) is SRAM, and the upper half is ROM mirror.
|
||||
// However, some cartridges maps the whole of bank (0x10000 bytes) to SRAM.
|
||||
// In that case, the upper half is probably mirrored as same as the lower half.
|
||||
|
||||
// create ram banks
|
||||
const uint32 bank_size = 0x8000;
|
||||
uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size;
|
||||
for ( uint32 mapped = 0, bank = start_bank; mapped < ram_chunks; bank++, mapped++ )
|
||||
{
|
||||
if ( bank == 0x7e )
|
||||
bank = 0xfe;
|
||||
|
||||
segment_t s;
|
||||
s.start_ea = uint32(bank << 16);
|
||||
s.end_ea = s.start_ea + bank_size;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank);
|
||||
if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_hirom_sram_offset(uint32 ram_size, uint8 start_bank)
|
||||
{
|
||||
// create ram banks
|
||||
const uint32 bank_size = 0x2000;
|
||||
uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size;
|
||||
for ( uint32 mapped = 0, bank = start_bank; mapped < ram_chunks; bank++, mapped++ )
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = uint32((bank << 16) + 0x6000);
|
||||
s.end_ea = s.start_ea + bank_size;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank);
|
||||
if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_lorom_sram(uint32 ram_size)
|
||||
{
|
||||
// create ram banks 70-7d (and fe-ff)
|
||||
map_lorom_sram_offset(ram_size, 0x70);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_hirom_sram(uint32 ram_size)
|
||||
{
|
||||
// create ram banks 20-3f
|
||||
map_hirom_sram_offset(ram_size, 0x20);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_superfx_sram(uint32 ram_size)
|
||||
{
|
||||
// create ram banks 70-71
|
||||
const uint32 bank_size = 0x10000;
|
||||
uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size;
|
||||
for ( uint32 mapped = 0, bank = 0x70; mapped < ram_chunks; bank++, mapped++ )
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = uint32(bank << 16);
|
||||
s.end_ea = s.start_ea + bank_size;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank);
|
||||
if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_superfx_workram()
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = 0x6000;
|
||||
s.end_ea = 0x8000;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), "sfxram");
|
||||
if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_superfx_hwregs()
|
||||
{
|
||||
map_io_seg(0x3000, 0x3500, "superfx");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_sa1_bwram(uint32 ram_size)
|
||||
{
|
||||
// create ram banks 40-41
|
||||
const uint32 bank_size = 0x10000;
|
||||
uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size;
|
||||
for ( uint32 mapped = 0, bank = 0x40; mapped < ram_chunks; bank++, mapped++ )
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = uint32(bank << 16);
|
||||
s.end_ea = s.start_ea + bank_size;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank);
|
||||
if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_sa1_iram()
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = 0x3000;
|
||||
s.end_ea = 0x3800;
|
||||
s.type = SEG_IMEM;
|
||||
s.sel = allocate_selector(s.start_ea >> 4);
|
||||
|
||||
char seg_name[0x10];
|
||||
qsnprintf(seg_name, sizeof(seg_name), "iram");
|
||||
if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) )
|
||||
loader_failure("Failed adding %s segment\n", seg_name);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_sa1_hwregs()
|
||||
{
|
||||
map_io_seg(0x2200, 0x2400, "sa1");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_cx4_hwregs()
|
||||
{
|
||||
map_io_seg(0x6000, 0x8000, "cx4");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_spc7110_hwregs()
|
||||
{
|
||||
map_io_seg(0x4800, 0x4840, "spc7110");
|
||||
map_io_seg(0x500000, 0x600000, "decomprom");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_sdd1_hwregs()
|
||||
{
|
||||
map_io_seg(0x4800, 0x4808, "sdd1");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_lorom_offset(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint8 start_bank, uint32 offset)
|
||||
{
|
||||
// 32KB chunks count
|
||||
uint32 chunks = (rom_size + 0x8000 - 1) / 0x8000;
|
||||
|
||||
// map rom to banks
|
||||
sel_t start_sel = 0;
|
||||
for ( uint32 mapped = 0, bank = start_bank; mapped < chunks; bank++, mapped++ )
|
||||
{
|
||||
if ( bank == 0x7e || bank == 0x7f )
|
||||
continue;
|
||||
|
||||
uint32 map_size = qmin(0x8000, rom_size - (0x8000 * mapped));
|
||||
|
||||
ea_t start = uint32((bank << 16) + 0x8000);
|
||||
ea_t end = start + 0x8000;
|
||||
uint32 off_in_file = rom_start_in_file + offset + (mapped << 15);
|
||||
|
||||
if ( !file2base(li, off_in_file, start, start + map_size, FILEREG_PATCHABLE) )
|
||||
loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", off_in_file, start, end);
|
||||
|
||||
char seg_name[0x10];
|
||||
sel_t selector = allocate_selector((start - 0x8000) >> 4);
|
||||
qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank);
|
||||
if ( !add_segm(selector, start, end, seg_name, "BANK_ROM") )
|
||||
loader_failure("Failed adding .BANK segment\n");
|
||||
|
||||
if ( bank == start_bank )
|
||||
start_sel = selector;
|
||||
}
|
||||
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_hirom_offset(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint8 start_bank, uint32 offset)
|
||||
{
|
||||
sel_t start_sel = 0;
|
||||
|
||||
// map rom to banks
|
||||
uint32 chunks = (rom_size + 0x10000 - 1) / 0x10000;
|
||||
for ( uint32 mapped = 0, bank = start_bank; mapped < chunks; bank++, mapped++ )
|
||||
{
|
||||
if ( bank == 0x7e || bank == 0x7f )
|
||||
continue;
|
||||
|
||||
uint32 map_size = qmin(0x10000, rom_size - (0x10000 * mapped));
|
||||
|
||||
ea_t start = uint32(bank << 16);
|
||||
ea_t end = start + 0x10000;
|
||||
uint32 off_in_file = rom_start_in_file + offset + (mapped << 16);
|
||||
if ( !file2base(li, off_in_file, start, start + map_size, FILEREG_PATCHABLE) )
|
||||
loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", off_in_file, start, end);
|
||||
|
||||
char seg_name[0x10];
|
||||
sel_t selector = allocate_selector((start) >> 4);
|
||||
qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank);
|
||||
if ( !add_segm(selector, start, end, seg_name, "BANK_ROM") )
|
||||
loader_failure("Failed adding .BANK segment\n");
|
||||
|
||||
if ( bank == start_bank )
|
||||
start_sel = selector;
|
||||
}
|
||||
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_lorom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size)
|
||||
{
|
||||
// map rom to banks 80-ff
|
||||
return map_lorom_offset(li, rom_start_in_file, rom_size, 0x80, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_hirom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size)
|
||||
{
|
||||
// map rom to banks c0-ff
|
||||
return map_hirom_offset(li, rom_start_in_file, rom_size, 0xc0, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_exhirom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size)
|
||||
{
|
||||
if ( rom_size <= 0x400000 )
|
||||
return BADSEL;
|
||||
|
||||
// map rom to banks 40-7f
|
||||
sel_t start_sel = map_hirom_offset(li, rom_start_in_file, rom_size - 0x400000, 0x40, 0x400000);
|
||||
|
||||
// map rom to banks c0-ff
|
||||
map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0xc0, 0);
|
||||
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_superfx(linput_t *li, uint32 rom_start_in_file, uint32 rom_size)
|
||||
{
|
||||
// map rom to banks 00-3f (LoROM layout)
|
||||
sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x00, 0);
|
||||
|
||||
// map rom to banks c0-df (HiROM layout)
|
||||
map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0xc0, 0);
|
||||
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_sa1(linput_t *li, uint32 rom_start_in_file, uint32 rom_size)
|
||||
{
|
||||
// map rom to banks 00-3f (LoROM layout)
|
||||
sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x00, 0);
|
||||
|
||||
// map rom to banks c0-ff (HiROM layout)
|
||||
map_hirom_offset(li, rom_start_in_file, rom_size, 0xc0, 0);
|
||||
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_sdd1rom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size)
|
||||
{
|
||||
// map rom to banks 80-bf (LoROM layout)
|
||||
sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x80, 0);
|
||||
|
||||
// map rom to banks c0-ff (HiROM layout)
|
||||
map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0xc0, 0);
|
||||
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_lorom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_lorom(li, rom_start_in_file, qmin(rom_size, 0x400000));
|
||||
map_lorom_sram(ram_size);
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_hirom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_hirom(li, rom_start_in_file, qmin(rom_size, 0x400000));
|
||||
map_hirom_sram(ram_size);
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_exlorom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
// S-DD1 cartridge should be handled by map_sdd1_cartridge
|
||||
sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x80, 0);
|
||||
map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0x40, 0);
|
||||
map_lorom_sram(ram_size);
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_exhirom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_exhirom(li, rom_start_in_file, rom_size);
|
||||
map_hirom_sram(ram_size);
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_superfx_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_superfx(li, rom_start_in_file, rom_size);
|
||||
map_superfx_sram(ram_size);
|
||||
map_superfx_workram();
|
||||
map_superfx_hwregs();
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_sa1_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_sa1(li, rom_start_in_file, rom_size);
|
||||
map_sa1_bwram(ram_size);
|
||||
map_sa1_iram();
|
||||
map_sa1_hwregs();
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_cx4_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_lorom(li, rom_start_in_file, qmin(rom_size, 0x400000));
|
||||
map_lorom_sram(ram_size);
|
||||
map_cx4_hwregs();
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_spc7110_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x100000), 0xc0, 0);
|
||||
// create ram banks 00-3f
|
||||
map_hirom_sram_offset(ram_size, 0x00);
|
||||
map_spc7110_hwregs();
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static sel_t map_sdd1_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size)
|
||||
{
|
||||
sel_t start_sel = map_sdd1rom(li, rom_start_in_file, rom_size);
|
||||
map_lorom_sram(ram_size);
|
||||
map_sdd1_hwregs();
|
||||
return start_sel;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_sharprtc()
|
||||
{
|
||||
map_io_seg(0x2800, 0x2802, "sharprtc");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_epsonrtc()
|
||||
{
|
||||
map_io_seg(0x4840, 0x4843, "epsonrtc");
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_obc1()
|
||||
{
|
||||
// TODO: Add OBC-1 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_dsp1(SuperFamicomCartridge::DSP1MemoryMapper /*dsp1_mapper*/)
|
||||
{
|
||||
// TODO: Add DSP-1 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_dsp2()
|
||||
{
|
||||
// TODO: Add DSP-2 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_dsp3()
|
||||
{
|
||||
// TODO: Add DSP-3 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_dsp4()
|
||||
{
|
||||
// TODO: Add DSP-4 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_st010()
|
||||
{
|
||||
// TODO: Add ST-010 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_st011()
|
||||
{
|
||||
// TODO: Add ST-011 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void map_st018()
|
||||
{
|
||||
// TODO: Add ST-018 registers
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static int idaapi accept_file(
|
||||
qstring *fileformatname,
|
||||
qstring *processor,
|
||||
linput_t *li,
|
||||
const char *)
|
||||
{
|
||||
SuperFamicomCartridge cartridge(li);
|
||||
unsigned score = SuperFamicomCartridge::score_header(li, cartridge.header_offset);
|
||||
|
||||
// It is enough to have the first byte of the supposed 'reset vector' match
|
||||
// one of 6 values, to have a treshold of 8. arm_eep0.bin has such a byte.
|
||||
// Thus a treshold of 9 (or more) seems in order. Here are some scores:
|
||||
// - m65816_ffVI.snes: 20
|
||||
// - m65816_pacman.snes: 14
|
||||
// - m65816_z2ybd.snes: 14
|
||||
const int ACCEPTABLE_SCORE_TRESHOLD = 9;
|
||||
if ( score >= ACCEPTABLE_SCORE_TRESHOLD
|
||||
&& cartridge.type != SuperFamicomCartridge::TypeUnknown )
|
||||
{
|
||||
*fileformatname = "SNES ROM";
|
||||
*processor = "m65816";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void add_interrupt_vector(snes_addr_t &sa, uint16 addr, const char *name, bool make_code)
|
||||
{
|
||||
// Set 'addr' as dword
|
||||
ea_t real_ea = sa.xlat(addr);
|
||||
create_word(real_ea, 2);
|
||||
|
||||
ea_t orig_vector_addr = get_word(real_ea);
|
||||
ea_t vector_addr = sa.xlat(orig_vector_addr);
|
||||
if ( orig_vector_addr != 0 && orig_vector_addr != 0xffff )
|
||||
{
|
||||
// Set 'vector_addr' name to be 'name'
|
||||
if ( !has_user_name(get_flags(vector_addr)) )
|
||||
set_name(vector_addr, name, SN_NOCHECK);
|
||||
|
||||
// Push the vector_addr into the autoanalysis queue.
|
||||
// Do not make use of auto_make_proc(), because some
|
||||
// interrupt handler functions are ``overlaid''. Thus,
|
||||
// we'd break a procedure w/ inserting another
|
||||
// procedure right into the previous procedure's code.
|
||||
if ( make_code )
|
||||
auto_make_code(vector_addr);
|
||||
|
||||
// Set 'real_ea' as offset
|
||||
refinfo_t ri;
|
||||
ri.init(REF_OFF16, vector_addr - orig_vector_addr);
|
||||
op_offset_ex(real_ea, OPND_MASK, &ri);
|
||||
|
||||
set_cmt(real_ea, name, false);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void idaapi load_file(linput_t *li, ushort /*neflags*/, const char * /*ffn*/)
|
||||
{
|
||||
// One should always set the processor type
|
||||
// as early as possible: IDA will draw some
|
||||
// informations from it; e.g., the size of segments.
|
||||
//
|
||||
// Should this instruction be placed after the calls to
|
||||
// map_mode_2x(), IDA would create 32-bits segments,
|
||||
// because, until the processor type is specified, IDA
|
||||
// assumes x86.
|
||||
set_processor_type("m65816", SETPROC_LOADER);
|
||||
|
||||
SuperFamicomCartridge cartridge(li);
|
||||
|
||||
// Determine whether ROM has a header
|
||||
int32 start = cartridge.has_copier_header ? 512 : 0;
|
||||
|
||||
// Store information for the cpu module
|
||||
netnode node;
|
||||
node.create("$ m65816");
|
||||
node.hashset("device", "snes");
|
||||
cartridge.write_hash(node);
|
||||
|
||||
snes_addr_t sa;
|
||||
sa.addr_init(cartridge);
|
||||
|
||||
sel_t start_cs;
|
||||
|
||||
if ( cartridge.has_cx4 )
|
||||
{
|
||||
start_cs = map_cx4_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
}
|
||||
else if ( cartridge.has_spc7110 )
|
||||
{
|
||||
start_cs = map_spc7110_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
}
|
||||
else if ( cartridge.has_sdd1 )
|
||||
{
|
||||
start_cs = map_sdd1_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( cartridge.mapper )
|
||||
{
|
||||
case SuperFamicomCartridge::LoROM:
|
||||
start_cs = map_lorom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
break;
|
||||
case SuperFamicomCartridge::HiROM:
|
||||
start_cs = map_hirom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
break;
|
||||
case SuperFamicomCartridge::ExLoROM:
|
||||
start_cs = map_exlorom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
break;
|
||||
case SuperFamicomCartridge::ExHiROM:
|
||||
start_cs = map_exhirom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
break;
|
||||
case SuperFamicomCartridge::SuperFXROM:
|
||||
start_cs = map_superfx_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
break;
|
||||
case SuperFamicomCartridge::SA1ROM:
|
||||
start_cs = map_sa1_cartridge(li, start, cartridge.rom_size, cartridge.ram_size);
|
||||
break;
|
||||
default:
|
||||
loader_failure("Unsupported mapper: %s", cartridge.mapper_string());
|
||||
}
|
||||
}
|
||||
inf_set_start_cs(start_cs);
|
||||
|
||||
// Hardware registers
|
||||
map_hwregs();
|
||||
|
||||
// WRAM
|
||||
map_wram();
|
||||
|
||||
if ( cartridge.has_sharprtc )
|
||||
map_sharprtc();
|
||||
|
||||
if ( cartridge.has_epsonrtc )
|
||||
map_epsonrtc();
|
||||
|
||||
if ( cartridge.has_obc1 )
|
||||
map_obc1();
|
||||
|
||||
if ( cartridge.has_dsp1 )
|
||||
map_dsp1(cartridge.dsp1_mapper);
|
||||
|
||||
if ( cartridge.has_dsp2 )
|
||||
map_dsp2();
|
||||
|
||||
if ( cartridge.has_dsp3 )
|
||||
map_dsp3();
|
||||
|
||||
if ( cartridge.has_dsp4 )
|
||||
map_dsp4();
|
||||
|
||||
if ( cartridge.has_st010 )
|
||||
map_st010();
|
||||
|
||||
if ( cartridge.has_st011 )
|
||||
map_st011();
|
||||
|
||||
if ( cartridge.has_st018 )
|
||||
map_st018();
|
||||
|
||||
ea_t reset_vector_loc = sa.xlat(0xfffc);
|
||||
uint16 start_pc = get_word(reset_vector_loc);
|
||||
ea_t start_address = sa.xlat(start_pc);
|
||||
inf_set_start_ip(start_address & 0xffff);
|
||||
|
||||
// ------- Most important vectors
|
||||
// http://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map
|
||||
add_interrupt_vector(sa, 0xfffc, "Emulation-mode RESET", true);
|
||||
add_interrupt_vector(sa, 0xffea, "Native-mode NMI", true);
|
||||
add_interrupt_vector(sa, 0xffee, "Native-mode IRQ", true);
|
||||
add_interrupt_vector(sa, 0xfffe, "Emulation-mode IRQ", true);
|
||||
|
||||
// ------- Native-mode vectors
|
||||
add_interrupt_vector(sa, 0xffe4, "Native-mode COP", false);
|
||||
add_interrupt_vector(sa, 0xffe6, "Native-mode BRK", false);
|
||||
add_interrupt_vector(sa, 0xffe8, "Native-mode ABORT", false);
|
||||
add_interrupt_vector(sa, 0xffec, "Native-mode RESET", false);
|
||||
|
||||
// ------- Emulation-mode vectors
|
||||
add_interrupt_vector(sa, 0xfff4, "Emulation-mode COP", false);
|
||||
add_interrupt_vector(sa, 0xfff8, "Emulation-mode ABORT", false);
|
||||
add_interrupt_vector(sa, 0xfffa, "Emulation-mode NMI", false);
|
||||
|
||||
// ------- Undefined vectors
|
||||
create_word(sa.xlat(0xffe0), 2);
|
||||
create_word(sa.xlat(0xffe2), 2);
|
||||
create_word(sa.xlat(0xfff0), 2);
|
||||
create_word(sa.xlat(0xfff2), 2);
|
||||
create_word(sa.xlat(0xfff6), 2);
|
||||
|
||||
// Header info
|
||||
ea_t header = sa.xlat(0xffc0);
|
||||
set_name(header, "snes_header");
|
||||
create_strlit(header, 21, STRTYPE_C);
|
||||
set_cmt(header, "Game Title", false);
|
||||
create_byte(header + 0x15, 1);
|
||||
set_cmt(header + 0x15, "ROM Makeup / ROM Speed and Map Mode", false);
|
||||
create_byte(header + 0x16, 1);
|
||||
set_cmt(header + 0x16, "Chipset", false);
|
||||
create_byte(header + 0x17, 1);
|
||||
set_cmt(header + 0x17, "ROM Size", false);
|
||||
create_byte(header + 0x18, 1);
|
||||
set_cmt(header + 0x18, "RAM Size", false);
|
||||
create_byte(header + 0x19, 1);
|
||||
set_cmt(header + 0x19, "Country", false);
|
||||
create_byte(header + 0x1a, 1);
|
||||
set_cmt(header + 0x1a, "Developer ID", false);
|
||||
create_byte(header + 0x1b, 1);
|
||||
set_cmt(header + 0x1b, "ROM Version", false);
|
||||
create_word(header + 0x1c, 2);
|
||||
set_cmt(header + 0x1c, "Checksum Complement", false);
|
||||
create_word(header + 0x1e, 2);
|
||||
set_cmt(header + 0x1e, "Checksum", false);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
loader_t LDSC =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
LDRF_RELOAD,
|
||||
accept_file,
|
||||
load_file,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
934
idasdk76/ldr/snes/super-famicom.hpp
Normal file
934
idasdk76/ldr/snes/super-famicom.hpp
Normal file
@@ -0,0 +1,934 @@
|
||||
/*
|
||||
SPECIAL LICENSE AGREEMENT
|
||||
|
||||
This file originally comes from the 'higan' emulator
|
||||
<http://byuu.org/emulation/higan/>, and should normally only be
|
||||
used in agreement with the terms of the GPLv3 license.
|
||||
|
||||
Hex-Rays has been granted, by written consent of its author, the use
|
||||
of this file within the scope of the 'snes' loader plugin, as well as
|
||||
within the scope of the '65816' processor module for the Interactive
|
||||
DisAssembler, without requiring Hex-Rays to release any other source code
|
||||
that composes the Interactive DisAssembler (or any of its plugins.)
|
||||
This special license agreement extends to anyone who may want to
|
||||
modify, re-compile & re-link the 'snes' loader or the '65816' processor
|
||||
module.
|
||||
|
||||
The stated agreement stands only for use of this file within the
|
||||
'snes' loader plugin and the '65816' processor module for the Interactive
|
||||
DisAssembler, and cannot be applied to any other project (other
|
||||
Interactive DisAssembler plugin, or unrelated project.)
|
||||
|
||||
Should this file be included in another project than the 'snes' loader
|
||||
or the '65816' processor module for the Interactive DisAssembler, the
|
||||
original GPLv3 licensing terms will apply.
|
||||
*/
|
||||
|
||||
// This file is included from the loader module and the processor module
|
||||
|
||||
// original source: higan/ananke/heuristics/super-famicom.hpp
|
||||
|
||||
#ifndef __SUPER_FAMICOM_HPP__
|
||||
#define __SUPER_FAMICOM_HPP__
|
||||
|
||||
struct SuperFamicomCartridge {
|
||||
SuperFamicomCartridge();
|
||||
SuperFamicomCartridge(linput_t *li);
|
||||
|
||||
//private:
|
||||
void read_header(linput_t *li);
|
||||
static unsigned find_header(linput_t *li);
|
||||
static unsigned score_header(linput_t *li, unsigned addr);
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
RomType = 0x16,
|
||||
RomSize = 0x17,
|
||||
RamSize = 0x18,
|
||||
CartRegion = 0x19,
|
||||
Company = 0x1a,
|
||||
Version = 0x1b,
|
||||
Complement = 0x1c, //inverse checksum
|
||||
Checksum = 0x1e,
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
enum Type {
|
||||
TypeNormal = 0,
|
||||
TypeBsxSlotted,
|
||||
TypeBsxBios,
|
||||
TypeBsx,
|
||||
TypeSufamiTurboBios,
|
||||
TypeSufamiTurbo,
|
||||
TypeSuperGameBoy1Bios,
|
||||
TypeSuperGameBoy2Bios,
|
||||
TypeGameBoy,
|
||||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC = 0,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM = 0,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SuperFXROM,
|
||||
SA1ROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
BSXROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped = 0,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
static inline const char * type_to_string(Type type);
|
||||
static inline Type string_to_type(const char * str);
|
||||
static inline const char * region_to_string(Region region);
|
||||
static inline Region string_to_region(const char * str);
|
||||
static inline const char * mapper_to_string(MemoryMapper mapper);
|
||||
static inline MemoryMapper string_to_mapper(const char * str);
|
||||
static inline const char * dsp1_mapper_to_string(DSP1MemoryMapper dsp1_mapper);
|
||||
static inline DSP1MemoryMapper string_to_dsp1_mapper(const char * str);
|
||||
|
||||
inline const char * type_string() const;
|
||||
inline const char * region_string() const;
|
||||
inline const char * mapper_string() const;
|
||||
inline const char * dsp1_mapper_string() const;
|
||||
|
||||
void read_hash(const netnode & node);
|
||||
void write_hash(netnode & node) const;
|
||||
void print() const;
|
||||
|
||||
unsigned rom_size;
|
||||
unsigned ram_size;
|
||||
bool firmware_appended; //true if firmware is appended to end of ROM data
|
||||
|
||||
bool has_copier_header;
|
||||
unsigned header_offset;
|
||||
|
||||
Type type;
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
|
||||
bool has_bsx_slot;
|
||||
bool has_superfx;
|
||||
bool has_sa1;
|
||||
bool has_sharprtc;
|
||||
bool has_epsonrtc;
|
||||
bool has_sdd1;
|
||||
bool has_spc7110;
|
||||
bool has_cx4;
|
||||
bool has_dsp1;
|
||||
bool has_dsp2;
|
||||
bool has_dsp3;
|
||||
bool has_dsp4;
|
||||
bool has_obc1;
|
||||
bool has_st010;
|
||||
bool has_st011;
|
||||
bool has_st018;
|
||||
};
|
||||
|
||||
SuperFamicomCartridge::SuperFamicomCartridge() :
|
||||
rom_size(0),
|
||||
ram_size(0),
|
||||
firmware_appended(false),
|
||||
has_copier_header(false),
|
||||
header_offset(0),
|
||||
type(TypeUnknown),
|
||||
region(NTSC),
|
||||
mapper(LoROM),
|
||||
dsp1_mapper(DSP1Unmapped),
|
||||
has_bsx_slot(false),
|
||||
has_superfx(false),
|
||||
has_sa1(false),
|
||||
has_sharprtc(false),
|
||||
has_epsonrtc(false),
|
||||
has_sdd1(false),
|
||||
has_spc7110(false),
|
||||
has_cx4(false),
|
||||
has_dsp1(false),
|
||||
has_dsp2(false),
|
||||
has_dsp3(false),
|
||||
has_dsp4(false),
|
||||
has_obc1(false),
|
||||
has_st010(false),
|
||||
has_st011(false),
|
||||
has_st018(false)
|
||||
{
|
||||
}
|
||||
|
||||
SuperFamicomCartridge::SuperFamicomCartridge(linput_t *li) {
|
||||
int32 size = qlsize(li);
|
||||
if(size < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
firmware_appended = false;
|
||||
|
||||
//skip copier header
|
||||
if((size & 0x7fff) == 512) size -= 512;
|
||||
|
||||
if(size < 0x8000) return;
|
||||
|
||||
read_header(li);
|
||||
|
||||
if(type == TypeGameBoy) return;
|
||||
if(type == TypeBsx) return;
|
||||
if(type == TypeSufamiTurbo) return;
|
||||
|
||||
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) {
|
||||
if((rom_size & 0x7fff) == 0x100) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0x100;
|
||||
}
|
||||
}
|
||||
|
||||
else if(has_cx4) {
|
||||
if((rom_size & 0x7fff) == 0xc00) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0xc00;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_dsp1) {
|
||||
if((size & 0x7fff) == 0x2000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_dsp2) {
|
||||
if((size & 0x7fff) == 0x2000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_dsp3) {
|
||||
if((size & 0x7fff) == 0x2000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_dsp4) {
|
||||
if((size & 0x7fff) == 0x2000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0x2000;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_st010) {
|
||||
if((size & 0xffff) == 0xd000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0xd000;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_st011) {
|
||||
if((size & 0xffff) == 0xd000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0xd000;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_st018) {
|
||||
if((size & 0x3ffff) == 0x28000) {
|
||||
firmware_appended = true;
|
||||
rom_size -= 0x28000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SuperFamicomCartridge::read_header(linput_t *li) {
|
||||
int32 size = qlsize(li);
|
||||
if(size < 0) return;
|
||||
|
||||
//skip copier header
|
||||
uint32 start = 0;
|
||||
has_copier_header = (size & 0x7fff) == 512;
|
||||
if(has_copier_header) start += 512, size -= 512;
|
||||
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
region = NTSC;
|
||||
rom_size = size;
|
||||
ram_size = 0;
|
||||
|
||||
has_bsx_slot = false;
|
||||
has_superfx = false;
|
||||
has_sa1 = false;
|
||||
has_sharprtc = false;
|
||||
has_epsonrtc = false;
|
||||
has_sdd1 = false;
|
||||
has_spc7110 = false;
|
||||
has_cx4 = false;
|
||||
has_dsp1 = false;
|
||||
has_dsp2 = false;
|
||||
has_dsp3 = false;
|
||||
has_dsp4 = false;
|
||||
has_obc1 = false;
|
||||
has_st010 = false;
|
||||
has_st011 = false;
|
||||
has_st018 = false;
|
||||
|
||||
//=====================
|
||||
//detect Game Boy carts
|
||||
//=====================
|
||||
|
||||
if(size >= 0x0140) {
|
||||
uint8 data[0x140];
|
||||
qlseek(li, start);
|
||||
qlread(li, data, 0x140);
|
||||
|
||||
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
|
||||
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
|
||||
type = TypeGameBoy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(size < 32768) {
|
||||
type = TypeUnknown;
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned index = find_header(li);
|
||||
header_offset = index;
|
||||
|
||||
uint8 extended_header[16 + 64];
|
||||
qlseek(li, start + index - 16);
|
||||
qlread(li, extended_header, 16 + 64);
|
||||
uint8 * header = &extended_header[16];
|
||||
|
||||
const uint8 mapperid = header[Mapper];
|
||||
const uint8 rom_type = header[RomType];
|
||||
const uint8 lrom_size = header[RomSize];
|
||||
const uint8 company = header[Company];
|
||||
const uint8 regionid = header[CartRegion] & 0x7f;
|
||||
|
||||
ram_size = 1024 << (header[RamSize] & 7);
|
||||
if(ram_size == 1024) ram_size = 0; //no RAM present
|
||||
if(lrom_size == 0 && ram_size) ram_size = 0; //fix for Bazooka Blitzkrieg's malformed header (swapped ROM and RAM sizes)
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;
|
||||
|
||||
//=======================
|
||||
//detect BS-X flash carts
|
||||
//=======================
|
||||
|
||||
if(header[0x13] == 0x00 || header[0x13] == 0xff) {
|
||||
if(header[0x14] == 0x00) {
|
||||
const uint8 n15 = header[0x15];
|
||||
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
|
||||
if(header[0x1a] == 0x33 || header[0x1a] == 0xff) {
|
||||
type = TypeBsx;
|
||||
mapper = BSXROM;
|
||||
region = NTSC; //BS-X only released in Japan
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================
|
||||
//detect Sufami Turbo carts
|
||||
//=========================
|
||||
|
||||
uint8 data[32];
|
||||
qlseek(li, start);
|
||||
qlread(li, data, 32);
|
||||
|
||||
if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
|
||||
if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
|
||||
type = TypeSufamiTurboBios;
|
||||
} else {
|
||||
type = TypeSufamiTurbo;
|
||||
}
|
||||
mapper = STROM;
|
||||
region = NTSC; //Sufami Turbo only released in Japan
|
||||
return; //RAM size handled outside this routine
|
||||
}
|
||||
|
||||
//==========================
|
||||
//detect Super Game Boy BIOS
|
||||
//==========================
|
||||
|
||||
if(!memcmp(header, "Super GAMEBOY2", 14)) {
|
||||
type = TypeSuperGameBoy2Bios;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!memcmp(header, "Super GAMEBOY", 13)) {
|
||||
type = TypeSuperGameBoy1Bios;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================
|
||||
//detect standard carts
|
||||
//=====================
|
||||
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
if(header[-14] == 'Z') {
|
||||
if(header[-11] == 'J') {
|
||||
uint8 n13 = header[-13];
|
||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||
if(company == 0x33 || (header[-10] == 0x00 && header[-4] == 0x00)) {
|
||||
has_bsx_slot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(has_bsx_slot) {
|
||||
if(!memcmp(header, "Satellaview BS-X ", 21)) {
|
||||
//BS-X base cart
|
||||
type = TypeBsxBios;
|
||||
mapper = BSXROM;
|
||||
region = NTSC; //BS-X only released in Japan
|
||||
return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
|
||||
} else {
|
||||
type = TypeBsxSlotted;
|
||||
mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
||||
region = NTSC; //BS-X slotted cartridges only released in Japan
|
||||
}
|
||||
} else {
|
||||
//standard cart
|
||||
type = TypeNormal;
|
||||
|
||||
if(index == 0x7fc0 && size >= 0x401000) {
|
||||
mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0 && mapperid == 0x32) {
|
||||
mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0) {
|
||||
mapper = LoROM;
|
||||
} else if(index == 0xffc0) {
|
||||
mapper = HiROM;
|
||||
} else { //index == 0x40ffc0
|
||||
mapper = ExHiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||
has_superfx = true;
|
||||
mapper = SuperFXROM;
|
||||
ram_size = 1024 << (header[-3] & 7);
|
||||
if(ram_size == 1024) ram_size = 0;
|
||||
}
|
||||
|
||||
if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
||||
has_sa1 = true;
|
||||
mapper = SA1ROM;
|
||||
}
|
||||
|
||||
if(mapperid == 0x35 && rom_type == 0x55) {
|
||||
has_sharprtc = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
has_sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||
has_spc7110 = true;
|
||||
has_epsonrtc = (rom_type == 0xf9);
|
||||
mapper = SPC7110ROM;
|
||||
}
|
||||
|
||||
if(mapperid == 0x20 && rom_type == 0xf3) {
|
||||
has_cx4 = true;
|
||||
}
|
||||
|
||||
if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(has_dsp1 == true) {
|
||||
if((mapperid & 0x2f) == 0x20 && size <= 0x100000) {
|
||||
dsp1_mapper = DSP1LoROM1MB;
|
||||
} else if((mapperid & 0x2f) == 0x20) {
|
||||
dsp1_mapper = DSP1LoROM2MB;
|
||||
} else if((mapperid & 0x2f) == 0x21) {
|
||||
dsp1_mapper = DSP1HiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapperid == 0x20 && rom_type == 0x05) {
|
||||
has_dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||
has_dsp3 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x03) {
|
||||
has_dsp4 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x25) {
|
||||
has_obc1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0xf6 && lrom_size >= 10) {
|
||||
has_st010 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0xf6 && lrom_size < 10) {
|
||||
has_st011 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0xf5) {
|
||||
has_st018 = true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned SuperFamicomCartridge::find_header(linput_t *li) {
|
||||
unsigned score_lo = score_header(li, 0x007fc0);
|
||||
unsigned score_hi = score_header(li, 0x00ffc0);
|
||||
unsigned score_ex = score_header(li, 0x40ffc0);
|
||||
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
return 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
return 0x00ffc0;
|
||||
} else {
|
||||
return 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned SuperFamicomCartridge::score_header(linput_t *li, unsigned addr) {
|
||||
int32 size = qlsize(li);
|
||||
if(size < 0x8000) return 0;
|
||||
|
||||
//skip copier header
|
||||
uint32 start = 0;
|
||||
if((size & 0x7fff) == 512) start += 512, size -= 512;
|
||||
|
||||
if((uint32)size < addr + 64) return 0; //image too small to contain header at this location?
|
||||
int score = 0;
|
||||
|
||||
uint8 header[64];
|
||||
qlseek(li, start + addr);
|
||||
qlread(li, header, 64);
|
||||
|
||||
uint16 resetvector = header[ResetVector] | (header[ResetVector + 1] << 8);
|
||||
uint16 checksum = header[Checksum ] | (header[Checksum + 1] << 8);
|
||||
uint16 complement = header[Complement ] | (header[Complement + 1] << 8);
|
||||
|
||||
uint32 resetop_addr = (addr & ~0x7fff) | (resetvector & 0x7fff);
|
||||
if(qlseek(li, start + resetop_addr) != (start + resetop_addr)) return 0;
|
||||
uint8 resetop;
|
||||
if(qlread(li, &resetop, sizeof(uint8)) != sizeof(uint8)) return 0; //first opcode executed upon reset
|
||||
|
||||
uint8 mapper = header[Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
|
||||
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
||||
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
||||
if(resetvector < 0x8000) return 0;
|
||||
|
||||
//some images duplicate the header in multiple locations, and others have completely
|
||||
//invalid header information that cannot be relied upon.
|
||||
//below code will analyze the first opcode executed at the specified reset vector to
|
||||
//determine the probability that this is the correct header.
|
||||
|
||||
//most likely opcodes
|
||||
if(resetop == 0x78 //sei
|
||||
|| resetop == 0x18 //clc (clc; xce)
|
||||
|| resetop == 0x38 //sec (sec; xce)
|
||||
|| resetop == 0x9c //stz $nnnn (stz $4200)
|
||||
|| resetop == 0x4c //jmp $nnnn
|
||||
|| resetop == 0x5c //jml $nnnnnn
|
||||
) score += 8;
|
||||
|
||||
//plausible opcodes
|
||||
if(resetop == 0xc2 //rep #$nn
|
||||
|| resetop == 0xe2 //sep #$nn
|
||||
|| resetop == 0xad //lda $nnnn
|
||||
|| resetop == 0xae //ldx $nnnn
|
||||
|| resetop == 0xac //ldy $nnnn
|
||||
|| resetop == 0xaf //lda $nnnnnn
|
||||
|| resetop == 0xa9 //lda #$nn
|
||||
|| resetop == 0xa2 //ldx #$nn
|
||||
|| resetop == 0xa0 //ldy #$nn
|
||||
|| resetop == 0x20 //jsr $nnnn
|
||||
|| resetop == 0x22 //jsl $nnnnnn
|
||||
) score += 4;
|
||||
|
||||
//implausible opcodes
|
||||
if(resetop == 0x40 //rti
|
||||
|| resetop == 0x60 //rts
|
||||
|| resetop == 0x6b //rtl
|
||||
|| resetop == 0xcd //cmp $nnnn
|
||||
|| resetop == 0xec //cpx $nnnn
|
||||
|| resetop == 0xcc //cpy $nnnn
|
||||
) score -= 4;
|
||||
|
||||
//least likely opcodes
|
||||
if(resetop == 0x00 //brk #$nn
|
||||
|| resetop == 0x02 //cop #$nn
|
||||
|| resetop == 0xdb //stp
|
||||
|| resetop == 0x42 //wdm
|
||||
|| resetop == 0xff //sbc $nnnnnn,x
|
||||
) score -= 8;
|
||||
|
||||
//at times, both the header and reset vector's first opcode will match ...
|
||||
//fallback and rely on info validity in these cases to determine more likely header.
|
||||
|
||||
//a valid checksum is the biggest indicator of a valid header.
|
||||
if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4;
|
||||
|
||||
if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
|
||||
if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
|
||||
if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
|
||||
if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
|
||||
|
||||
if(header[Company] == 0x33) score += 2; //0x33 indicates extended header
|
||||
if(header[RomType] < 0x08) score++;
|
||||
if(header[RomSize] < 0x10) score++;
|
||||
if(header[RamSize] < 0x08) score++;
|
||||
if(header[CartRegion] < 14) score++;
|
||||
|
||||
if(score < 0) score = 0;
|
||||
return score;
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::type_to_string(Type type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case TypeNormal:
|
||||
return "TypeNormal";
|
||||
|
||||
case TypeBsxSlotted:
|
||||
return "TypeBsxSlotted";
|
||||
|
||||
case TypeBsxBios:
|
||||
return "TypeBsxBios";
|
||||
|
||||
case TypeBsx:
|
||||
return "TypeBsx";
|
||||
|
||||
case TypeSufamiTurboBios:
|
||||
return "TypeSufamiTurboBios";
|
||||
|
||||
case TypeSufamiTurbo:
|
||||
return "TypeSufamiTurbo";
|
||||
|
||||
case TypeSuperGameBoy1Bios:
|
||||
return "TypeSuperGameBoy1Bios";
|
||||
|
||||
case TypeSuperGameBoy2Bios:
|
||||
return "TypeSuperGameBoy2Bios";
|
||||
|
||||
case TypeGameBoy:
|
||||
return "TypeGameBoy";
|
||||
|
||||
case TypeUnknown:
|
||||
return "TypeUnknown";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SuperFamicomCartridge::Type SuperFamicomCartridge::string_to_type(const char * str)
|
||||
{
|
||||
if (streq(str, "TypeNormal"))
|
||||
return TypeNormal;
|
||||
else if (streq(str, "TypeBsxSlotted"))
|
||||
return TypeBsxSlotted;
|
||||
else if (streq(str, "TypeBsxBios"))
|
||||
return TypeBsxBios;
|
||||
else if (streq(str, "TypeBsx"))
|
||||
return TypeBsx;
|
||||
else if (streq(str, "TypeSufamiTurboBios"))
|
||||
return TypeSufamiTurboBios;
|
||||
else if (streq(str, "TypeSufamiTurbo"))
|
||||
return TypeSufamiTurbo;
|
||||
else if (streq(str, "TypeSuperGameBoy1Bios"))
|
||||
return TypeSuperGameBoy1Bios;
|
||||
else if (streq(str, "TypeSuperGameBoy2Bios"))
|
||||
return TypeSuperGameBoy2Bios;
|
||||
else if (streq(str, "TypeGameBoy"))
|
||||
return TypeGameBoy;
|
||||
else if (streq(str, "TypeUnknown"))
|
||||
return TypeUnknown;
|
||||
else
|
||||
return TypeUnknown;
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::region_to_string(Region region)
|
||||
{
|
||||
switch(region)
|
||||
{
|
||||
case NTSC:
|
||||
return "NTSC";
|
||||
|
||||
case PAL:
|
||||
return "PAL";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SuperFamicomCartridge::Region SuperFamicomCartridge::string_to_region(const char * str)
|
||||
{
|
||||
if (streq(str, "NTSC"))
|
||||
return NTSC;
|
||||
else if (streq(str, "PAL"))
|
||||
return PAL;
|
||||
else
|
||||
return NTSC;
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::mapper_to_string(MemoryMapper mapper)
|
||||
{
|
||||
switch(mapper)
|
||||
{
|
||||
case LoROM:
|
||||
return "LoROM";
|
||||
|
||||
case HiROM:
|
||||
return "HiROM";
|
||||
|
||||
case ExLoROM:
|
||||
return "ExLoROM";
|
||||
|
||||
case ExHiROM:
|
||||
return "ExHiROM";
|
||||
|
||||
case SuperFXROM:
|
||||
return "SuperFXROM";
|
||||
|
||||
case SA1ROM:
|
||||
return "SA1ROM";
|
||||
|
||||
case SPC7110ROM:
|
||||
return "SPC7110ROM";
|
||||
|
||||
case BSCLoROM:
|
||||
return "BSCLoROM";
|
||||
|
||||
case BSCHiROM:
|
||||
return "BSCHiROM";
|
||||
|
||||
case BSXROM:
|
||||
return "BSXROM";
|
||||
|
||||
case STROM:
|
||||
return "STROM";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SuperFamicomCartridge::MemoryMapper SuperFamicomCartridge::string_to_mapper(const char * str)
|
||||
{
|
||||
if (streq(str, "LoROM"))
|
||||
return LoROM;
|
||||
else if (streq(str, "HiROM"))
|
||||
return HiROM;
|
||||
else if (streq(str, "ExLoROM"))
|
||||
return ExLoROM;
|
||||
else if (streq(str, "ExHiROM"))
|
||||
return ExHiROM;
|
||||
else if (streq(str, "SuperFXROM"))
|
||||
return SuperFXROM;
|
||||
else if (streq(str, "SA1ROM"))
|
||||
return SA1ROM;
|
||||
else if (streq(str, "SPC7110ROM"))
|
||||
return SPC7110ROM;
|
||||
else if (streq(str, "BSCLoROM"))
|
||||
return BSCLoROM;
|
||||
else if (streq(str, "BSCHiROM"))
|
||||
return BSCHiROM;
|
||||
else if (streq(str, "BSXROM"))
|
||||
return BSXROM;
|
||||
else if (streq(str, "STROM"))
|
||||
return STROM;
|
||||
else
|
||||
return LoROM;
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::dsp1_mapper_to_string(DSP1MemoryMapper dsp1_mapper)
|
||||
{
|
||||
switch(dsp1_mapper)
|
||||
{
|
||||
case DSP1Unmapped:
|
||||
return "DSP1Unmapped";
|
||||
|
||||
case DSP1LoROM1MB:
|
||||
return "DSP1LoROM1MB";
|
||||
|
||||
case DSP1LoROM2MB:
|
||||
return "DSP1LoROM2MB";
|
||||
|
||||
case DSP1HiROM:
|
||||
return "DSP1HiROM";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SuperFamicomCartridge::DSP1MemoryMapper SuperFamicomCartridge::string_to_dsp1_mapper(const char * str)
|
||||
{
|
||||
if (streq(str, "DSP1Unmapped"))
|
||||
return DSP1Unmapped;
|
||||
else if (streq(str, "DSP1LoROM1MB"))
|
||||
return DSP1LoROM1MB;
|
||||
else if (streq(str, "DSP1LoROM2MB"))
|
||||
return DSP1LoROM2MB;
|
||||
else if (streq(str, "DSP1HiROM"))
|
||||
return DSP1HiROM;
|
||||
else
|
||||
return DSP1Unmapped;
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::type_string() const
|
||||
{
|
||||
return type_to_string(type);
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::region_string() const
|
||||
{
|
||||
return region_to_string(region);
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::mapper_string() const
|
||||
{
|
||||
return mapper_to_string(mapper);
|
||||
}
|
||||
|
||||
const char * SuperFamicomCartridge::dsp1_mapper_string() const
|
||||
{
|
||||
return dsp1_mapper_to_string(dsp1_mapper);
|
||||
}
|
||||
|
||||
void SuperFamicomCartridge::read_hash(const netnode & node)
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
ssize_t len;
|
||||
|
||||
rom_size = node.hashval_long("rom_size");
|
||||
ram_size = node.hashval_long("ram_size");
|
||||
firmware_appended = node.hashval_long("firmware_appended") != 0;
|
||||
|
||||
header_offset = node.hashval_long("header_offset");
|
||||
|
||||
len = node.hashstr("type", buf, sizeof(buf));
|
||||
if(len >= 0) type = string_to_type(buf);
|
||||
len = node.hashstr("region", buf, sizeof(buf));
|
||||
if(len >= 0) region = string_to_region(buf);
|
||||
len = node.hashstr("mapper", buf, sizeof(buf));
|
||||
if(len >= 0) mapper = string_to_mapper(buf);
|
||||
len = node.hashstr("dsp1_mapper", buf, sizeof(buf));
|
||||
if(len >= 0) dsp1_mapper = string_to_dsp1_mapper(buf);
|
||||
|
||||
has_bsx_slot = node.hashval_long("has_bsx_slot") != 0;
|
||||
has_superfx = node.hashval_long("has_superfx") != 0;
|
||||
has_sa1 = node.hashval_long("has_sa1") != 0;
|
||||
has_sharprtc = node.hashval_long("has_sharprtc") != 0;
|
||||
has_epsonrtc = node.hashval_long("has_epsonrtc") != 0;
|
||||
has_sdd1 = node.hashval_long("has_sdd1") != 0;
|
||||
has_spc7110 = node.hashval_long("has_spc7110") != 0;
|
||||
has_cx4 = node.hashval_long("has_cx4") != 0;
|
||||
has_dsp1 = node.hashval_long("has_dsp1") != 0;
|
||||
has_dsp2 = node.hashval_long("has_dsp2") != 0;
|
||||
has_dsp3 = node.hashval_long("has_dsp3") != 0;
|
||||
has_dsp4 = node.hashval_long("has_dsp4") != 0;
|
||||
has_obc1 = node.hashval_long("has_obc1") != 0;
|
||||
has_st010 = node.hashval_long("has_st010") != 0;
|
||||
has_st011 = node.hashval_long("has_st011") != 0;
|
||||
has_st018 = node.hashval_long("has_st018") != 0;
|
||||
}
|
||||
|
||||
void SuperFamicomCartridge::write_hash(netnode & node) const
|
||||
{
|
||||
node.hashset("rom_size", rom_size);
|
||||
node.hashset("ram_size", ram_size);
|
||||
node.hashset("firmware_appended", firmware_appended ? 1 : 0);
|
||||
|
||||
node.hashset("header_offset", header_offset);
|
||||
|
||||
node.hashset("type", type_string());
|
||||
node.hashset("region", region_string());
|
||||
node.hashset("mapper", mapper_string());
|
||||
node.hashset("dsp1_mapper", dsp1_mapper_string());
|
||||
|
||||
node.hashset("has_bsx_slot", has_bsx_slot ? 1 : 0);
|
||||
node.hashset("has_superfx", has_superfx ? 1 : 0);
|
||||
node.hashset("has_sa1", has_sa1 ? 1 : 0);
|
||||
node.hashset("has_sharprtc", has_sharprtc ? 1 : 0);
|
||||
node.hashset("has_epsonrtc", has_epsonrtc ? 1 : 0);
|
||||
node.hashset("has_sdd1", has_sdd1 ? 1 : 0);
|
||||
node.hashset("has_spc7110", has_spc7110 ? 1 : 0);
|
||||
node.hashset("has_cx4", has_cx4 ? 1 : 0);
|
||||
node.hashset("has_dsp1", has_dsp1 ? 1 : 0);
|
||||
node.hashset("has_dsp2", has_dsp2 ? 1 : 0);
|
||||
node.hashset("has_dsp3", has_dsp3 ? 1 : 0);
|
||||
node.hashset("has_dsp4", has_dsp4 ? 1 : 0);
|
||||
node.hashset("has_obc1", has_obc1 ? 1 : 0);
|
||||
node.hashset("has_st010", has_st010 ? 1 : 0);
|
||||
node.hashset("has_st011", has_st011 ? 1 : 0);
|
||||
node.hashset("has_st018", has_st018 ? 1 : 0);
|
||||
}
|
||||
|
||||
void SuperFamicomCartridge::print() const
|
||||
{
|
||||
// print informations for debug purpose
|
||||
msg("SuperFamicomCartridge::rom_size=%d\n", rom_size);
|
||||
msg("SuperFamicomCartridge::ram_size=%d\n", ram_size);
|
||||
msg("SuperFamicomCartridge::firmware_appended=%s\n", firmware_appended ? "true" : "false");
|
||||
|
||||
msg("SuperFamicomCartridge::has_copier_header=%s\n", has_copier_header ? "true" : "false");
|
||||
msg("SuperFamicomCartridge::header_offset=0x%04X\n", header_offset);
|
||||
|
||||
msg("SuperFamicomCartridge::type=%d\n", type);
|
||||
msg("SuperFamicomCartridge::region=%d\n", region);
|
||||
msg("SuperFamicomCartridge::mapper=%d\n", mapper);
|
||||
msg("SuperFamicomCartridge::dsp1_mapper=%d\n", dsp1_mapper);
|
||||
|
||||
msg("SuperFamicomCartridge::extra_chips=[");
|
||||
if(has_bsx_slot) msg(" BSX Slot");
|
||||
if(has_superfx) msg(" SuperFX");
|
||||
if(has_sa1) msg(" SA1");
|
||||
if(has_sharprtc) msg(" Sharp RTC");
|
||||
if(has_epsonrtc) msg(" Epson RTC");
|
||||
if(has_sdd1) msg(" SDD1");
|
||||
if(has_spc7110) msg(" SPC7110");
|
||||
if(has_cx4) msg(" CX4");
|
||||
if(has_dsp1) msg(" DSP1");
|
||||
if(has_dsp2) msg(" DSP2");
|
||||
if(has_dsp3) msg(" DSP3");
|
||||
if(has_dsp4) msg(" DSP4");
|
||||
if(has_obc1) msg(" OBC1");
|
||||
if(has_st010) msg(" ST010");
|
||||
if(has_st011) msg(" ST011");
|
||||
if(has_st018) msg(" ST018");
|
||||
msg(" ]\n");
|
||||
}
|
||||
|
||||
#endif //__SUPER_FAMICOM_HPP__
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user