update to ida 7.6, add builds

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

427
idasdk76/ldr/aif/aif.cpp Normal file
View 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 *)&sect->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
View 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

View 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
View 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