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
|
||||
Reference in New Issue
Block a user