1043 lines
38 KiB
C++
1043 lines
38 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Copyright (c) 1990-2021 Hex-Rays
|
|
* ALL RIGHTS RESERVED.
|
|
*
|
|
*/
|
|
|
|
#ifndef _LOADER_HPP
|
|
#define _LOADER_HPP
|
|
#include <ida.hpp>
|
|
|
|
/*! \file loader.hpp
|
|
|
|
\brief Definitions of IDP, LDR, PLUGIN module interfaces
|
|
|
|
This file also contains:
|
|
- functions to load files into the database
|
|
- functions to generate output files
|
|
- high level functions to work with the database (open, save, close)
|
|
|
|
The LDR interface consists of one structure: loader_t \n
|
|
The IDP interface consists of one structure: processor_t \n
|
|
The PLUGIN interface consists of one structure: plugin_t
|
|
|
|
Modules can't use standard FILE* functions.
|
|
They must use functions from <fpro.h>
|
|
|
|
Modules can't use standard memory allocation functions.
|
|
They must use functions from <pro.h>
|
|
|
|
The exported entry #1 in the module should point to the
|
|
the appropriate structure. (loader_t for LDR module, for example)
|
|
*/
|
|
|
|
//----------------------------------------------------------------------
|
|
// DEFINITION OF LDR MODULES
|
|
//----------------------------------------------------------------------
|
|
|
|
class linput_t; // loader input source. see diskio.hpp for the functions
|
|
struct extlang_t; // check expr.hpp
|
|
struct plugmod_t; // idp.hpp
|
|
|
|
/// Loader description block - must be exported from the loader module
|
|
struct loader_t
|
|
{
|
|
uint32 version; ///< api version, should be #IDP_INTERFACE_VERSION
|
|
uint32 flags; ///< \ref LDRF_
|
|
/// \defgroup LDRF_ Loader flags
|
|
/// Used by loader_t::flags
|
|
//@{
|
|
#define LDRF_RELOAD 0x0001 ///< loader recognizes #NEF_RELOAD flag
|
|
#define LDRF_REQ_PROC 0x0002 ///< Requires a processor to be set.
|
|
///< if this bit is not set, load_file() must
|
|
///< call set_processor_type(..., SETPROC_LOADER)
|
|
//@}
|
|
|
|
/// Check input file format.
|
|
/// This function will be called one or more times depending on the result value.
|
|
/// \param[out] fileformat name of file format
|
|
/// \param[out] processor desired processor (optional)
|
|
/// \param li input file
|
|
/// \param filename name of the input file,
|
|
/// if it is an archive member name then the actual file doesn't exist
|
|
/// \return
|
|
/// 1 if file format is recognized, and fills 'fileformatname', otherwise returns 0.
|
|
/// This function may return a unique file format number instead of 1.
|
|
/// To get this unique number, please contact the author.
|
|
/// If the return value is ORed with #ACCEPT_ARCHIVE, then
|
|
/// it is an archive loader. Its process_archive() will be called
|
|
/// instead of load_file().
|
|
/// If the return value is ORed with #ACCEPT_CONTINUE, then
|
|
/// this function will be called another time.
|
|
/// If the return value is ORed with #ACCEPT_FIRST, then this format
|
|
/// should be placed first in the "load file" dialog box.
|
|
/// In the sorting order of file formats the archive formats have priority.
|
|
int (idaapi *accept_file)(
|
|
qstring *fileformatname,
|
|
qstring *processor,
|
|
linput_t *li,
|
|
const char *filename);
|
|
|
|
/// Specify that a file format is served by archive loader
|
|
/// See loader_t::accept_file
|
|
#define ACCEPT_ARCHIVE 0x2000
|
|
/// Specify that the function must be called another time
|
|
/// See loader_t::accept_file
|
|
#define ACCEPT_CONTINUE 0x4000
|
|
/// Specify that a file format should be place first in "load file" dialog box.
|
|
/// See loader_t::accept_file
|
|
#define ACCEPT_FIRST 0x8000
|
|
|
|
/// Load file into the database.
|
|
/// \param li input file
|
|
/// \param neflags \ref NEF_
|
|
/// \param fileformatname name of type of the file
|
|
/// (it was returned by #accept_file)
|
|
///
|
|
/// If this function fails, loader_failure() should be called
|
|
void (idaapi *load_file)(
|
|
linput_t *li,
|
|
ushort neflags,
|
|
const char *fileformatname);
|
|
/// \defgroup NEF_ Load file flags
|
|
/// Passed as 'neflags' parameter to loader_t::load_file
|
|
//@{
|
|
#define NEF_SEGS 0x0001 ///< Create segments
|
|
#define NEF_RSCS 0x0002 ///< Load resources
|
|
#define NEF_NAME 0x0004 ///< Rename entries
|
|
#define NEF_MAN 0x0008 ///< Manual load
|
|
#define NEF_FILL 0x0010 ///< Fill segment gaps
|
|
#define NEF_IMPS 0x0020 ///< Create import segment
|
|
#define NEF_FIRST 0x0080 ///< This is the first file loaded
|
|
///< into the database.
|
|
#define NEF_CODE 0x0100 ///< for load_binary_file():
|
|
///< load as a code segment
|
|
#define NEF_RELOAD 0x0200 ///< reload the file at the same place:
|
|
///< - don't create segments
|
|
///< - don't create fixup info
|
|
///< - don't import segments
|
|
///< - etc
|
|
///< load only the bytes into the base.
|
|
///< a loader should have #LDRF_RELOAD
|
|
///< bit set
|
|
#define NEF_FLAT 0x0400 ///< Autocreate FLAT group (PE)
|
|
#define NEF_MINI 0x0800 ///< Create mini database (do not copy
|
|
///< segment bytes from the input file;
|
|
///< use only the file header metadata)
|
|
#define NEF_LOPT 0x1000 ///< Display additional loader options dialog
|
|
#define NEF_LALL 0x2000 ///< Load all segments without questions
|
|
//@}
|
|
|
|
/// Create output file from the database.
|
|
/// This function may be absent.
|
|
/// If fp == NULL, then this function returns:
|
|
/// - 0: can't create file of this type
|
|
/// - 1: ok, can create file of this type
|
|
///
|
|
/// If fp != NULL, then this function should create the output file
|
|
int (idaapi *save_file)(FILE *fp, const char *fileformatname);
|
|
|
|
/// Take care of a moved segment (fix up relocations, for example).
|
|
/// This function may be absent.
|
|
/// A special calling method \code move_segm(BADADDR, delta, 0, formatname); \endcode
|
|
/// means that the whole program has been moved in the memory (rebased) by delta bytes
|
|
/// \param from previous linear address of the segment
|
|
/// \param to current linear address of the segment
|
|
/// \param size size of the moved segment
|
|
/// \param fileformatname the file format
|
|
/// \retval 1 ok
|
|
/// \retval 0 failure
|
|
int (idaapi *move_segm)(
|
|
ea_t from,
|
|
ea_t to,
|
|
asize_t size,
|
|
const char *fileformatname);
|
|
|
|
/// Display list of archive members and let the user select one.
|
|
/// Extract the selected archive member into a temporary file.
|
|
/// \param[out] temp_file name of the file with the extracted archive member.
|
|
/// \param li input file
|
|
/// \param[in,out] module_name in: name of archive
|
|
/// out: name of the extracted archive member
|
|
/// \param[in,out] neflags \ref NEF_
|
|
/// \param fileformatname name of type of the file
|
|
/// (it was returned by #accept_file)
|
|
/// \param defmember extract the specified member,
|
|
/// for example "subdir/member.exe",
|
|
/// may be NULL
|
|
/// \param errbuf error message if 0 is returned,
|
|
/// may be NULL
|
|
/// \return -1-cancelled by the user, 1-ok, 0-error, see errbuf for details
|
|
int (idaapi *process_archive)(
|
|
qstring *temp_file,
|
|
linput_t *li,
|
|
qstring *module_name,
|
|
ushort *neflags,
|
|
const char *fileformatname,
|
|
const char *defmember,
|
|
qstring *errbuf);
|
|
};
|
|
|
|
|
|
/// See loader_failure()
|
|
|
|
idaman AS_PRINTF(1, 0) NORETURN void ida_export vloader_failure(const char *format, va_list va);
|
|
|
|
|
|
/// Display a message about a loader failure and stop the loading process.
|
|
/// The kernel will destroy the database.
|
|
/// If format == NULL, no message will be displayed
|
|
/// This function does not return (it longjumps)!
|
|
/// It may be called only from loader_t::load_file
|
|
|
|
AS_PRINTF(1, 2) NORETURN inline void loader_failure(const char *format=NULL, ...)
|
|
{
|
|
va_list va;
|
|
va_start(va, format);
|
|
vloader_failure(format, va);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
#if defined(__NT__)
|
|
# define DLLEXT "dll"
|
|
#elif defined(__LINUX__)
|
|
# define DLLEXT "so"
|
|
#elif defined(__MAC__)
|
|
# define DLLEXT "dylib"
|
|
#else
|
|
# error Unknown loader ext
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------
|
|
/// \def{LOADER_DLL, Pattern to find loader files}
|
|
#ifdef __EA64__
|
|
# define LOADER_DLL "*64." DLLEXT
|
|
#else
|
|
# define LOADER_DLL "*." DLLEXT
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------
|
|
// Functions for the UI to load files
|
|
//----------------------------------------------------------------------
|
|
/// List of loaders
|
|
struct load_info_t
|
|
{
|
|
load_info_t *next;
|
|
qstring dllname;
|
|
qstring ftypename;
|
|
qstring processor; ///< desired processor name
|
|
filetype_t ftype;
|
|
uint32 loader_flags; ///< copy of loader_t::flags
|
|
uint32 lflags; ///< \ref LIF_
|
|
int pri; ///< 2-archldr, 1-place first, 0-normal priority
|
|
|
|
/// \defgroup LIF_ loader info flags
|
|
/// Used by load_info_t::lflags
|
|
//@{
|
|
#define LIF_ARCHLDR 0x0001 ///< archive loader
|
|
//@}
|
|
|
|
bool is_archldr(void) { return (lflags & LIF_ARCHLDR) != 0; }
|
|
};
|
|
DECLARE_TYPE_AS_MOVABLE(load_info_t);
|
|
|
|
/// Build list of potential loaders
|
|
|
|
idaman load_info_t *ida_export build_loaders_list(linput_t *li, const char *filename);
|
|
|
|
|
|
/// Free the list of loaders
|
|
|
|
idaman void ida_export free_loaders_list(load_info_t *list);
|
|
|
|
|
|
/// Get name of loader from its DLL file
|
|
/// (for example, for PE files we will get "PE").
|
|
/// This function modifies the original string and returns a pointer into it.
|
|
/// NB: if the file extension is a registered extlang extension (e.g. py or idc)
|
|
/// the extension is retained
|
|
|
|
idaman char *ida_export get_loader_name_from_dll(char *dllname);
|
|
|
|
|
|
/// Get name of loader used to load the input file into the database.
|
|
/// If no external loader was used, returns -1.
|
|
/// Otherwise copies the loader file name without the extension in the buf
|
|
/// and returns its length
|
|
/// (for example, for PE files we will get "PE").
|
|
/// For scripted loaders, the file extension is retained.
|
|
|
|
idaman ssize_t ida_export get_loader_name(char *buf, size_t bufsize);
|
|
|
|
|
|
/// Load a binary file into the database.
|
|
/// This function usually is called from ui.
|
|
/// \param filename the name of input file as is
|
|
/// (if the input file is from library, then
|
|
/// this is the name from the library)
|
|
/// \param li loader input source
|
|
/// \param _neflags \ref NEF_. For the first file,
|
|
/// the flag #NEF_FIRST must be set.
|
|
/// \param fileoff Offset in the input file
|
|
/// \param basepara Load address in paragraphs
|
|
/// \param binoff Load offset (load_address=(basepara<<4)+binoff)
|
|
/// \param nbytes Number of bytes to load from the file.
|
|
/// - 0: up to the end of the file
|
|
///
|
|
/// If nbytes is bigger than the number of
|
|
/// bytes rest, the kernel will load as much
|
|
/// as possible
|
|
/// \retval true ok
|
|
/// \retval false failed (couldn't open the file)
|
|
|
|
idaman bool ida_export load_binary_file(
|
|
const char *filename,
|
|
linput_t *li,
|
|
ushort _neflags,
|
|
qoff64_t fileoff,
|
|
ea_t basepara,
|
|
ea_t binoff,
|
|
uint64 nbytes);
|
|
|
|
|
|
/// Load a non-binary file into the database.
|
|
/// This function usually is called from ui.
|
|
/// \param filename the name of input file as is
|
|
/// (if the input file is from library, then
|
|
/// this is the name from the library)
|
|
/// \param li loader input source
|
|
/// \param sysdlldir a directory with system dlls. Pass "." if unknown.
|
|
/// \param _neflags \ref NEF_. For the first file
|
|
/// the flag #NEF_FIRST must be set.
|
|
/// \param loader pointer to ::load_info_t structure.
|
|
/// If the current IDP module has \ph{loader} != NULL
|
|
/// then this argument is ignored.
|
|
/// \return success
|
|
|
|
idaman bool ida_export load_nonbinary_file(
|
|
const char *filename,
|
|
linput_t *li,
|
|
const char *sysdlldir,
|
|
ushort _neflags,
|
|
load_info_t *loader);
|
|
|
|
|
|
/// Calls loader_t::process_archive()
|
|
/// For parameters and return value description
|
|
/// look at loader_t::process_archive().
|
|
/// Additional parameter:
|
|
/// \param loader pointer to ::load_info_t structure.
|
|
|
|
idaman int ida_export process_archive(
|
|
qstring *temp_file,
|
|
linput_t *li,
|
|
qstring *module_name,
|
|
ushort *neflags,
|
|
const char *defmember,
|
|
const load_info_t *loader,
|
|
qstring *errbuf=NULL);
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// Output file types
|
|
enum ofile_type_t
|
|
{
|
|
OFILE_MAP = 0, ///< MAP file
|
|
OFILE_EXE = 1, ///< Executable file
|
|
OFILE_IDC = 2, ///< IDC file
|
|
OFILE_LST = 3, ///< Disassembly listing
|
|
OFILE_ASM = 4, ///< Assembly
|
|
OFILE_DIF = 5, ///< Difference
|
|
};
|
|
|
|
//------------------------------------------------------------------
|
|
/// Generate an output file.
|
|
/// \param otype type of output file.
|
|
/// \param fp the output file handle
|
|
/// \param ea1 start address. For some file types this argument is ignored
|
|
/// \param ea2 end address. For some file types this argument is ignored
|
|
/// as usual in ida, the end address of the range is not included
|
|
/// \param flags \ref GENFLG_
|
|
///
|
|
/// For ::OFILE_EXE:
|
|
/// \retval 0 can't generate exe file
|
|
/// \retval 1 ok
|
|
///
|
|
/// For other file types:
|
|
/// \return number of the generated lines. -1 if an error occurred
|
|
|
|
idaman int ida_export gen_file(ofile_type_t otype, FILE *fp, ea_t ea1, ea_t ea2, int flags);
|
|
|
|
/// \defgroup GENFLG_ Generate file flags
|
|
/// Passed as 'flags' parameter to gen_file()
|
|
//@{
|
|
#define GENFLG_MAPSEG 0x0001 ///< ::OFILE_MAP: generate map of segments
|
|
#define GENFLG_MAPNAME 0x0002 ///< ::OFILE_MAP: include dummy names
|
|
#define GENFLG_MAPDMNG 0x0004 ///< ::OFILE_MAP: demangle names
|
|
#define GENFLG_MAPLOC 0x0008 ///< ::OFILE_MAP: include local names
|
|
#define GENFLG_IDCTYPE 0x0008 ///< ::OFILE_IDC: gen only information about types
|
|
#define GENFLG_ASMTYPE 0x0010 ///< ::OFILE_ASM,::OFILE_LST: gen information about types too
|
|
#define GENFLG_GENHTML 0x0020 ///< ::OFILE_ASM,::OFILE_LST: generate html (::ui_genfile_callback will be used)
|
|
#define GENFLG_ASMINC 0x0040 ///< ::OFILE_ASM,::OFILE_LST: gen information only about types
|
|
//@}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Helper functions for the loaders & ui
|
|
//----------------------------------------------------------------------
|
|
|
|
/// Load portion of file into the database.
|
|
/// This function will include (ea1..ea2) into the addressing space of the
|
|
/// program (make it enabled).
|
|
/// \param li pointer of input source
|
|
/// \param pos position in the file
|
|
/// \param ea1,ea2 range of destination linear addresses
|
|
/// \param patchable should the kernel remember correspondence of
|
|
/// file offsets to linear addresses.
|
|
/// \retval 1 ok
|
|
/// \retval 0 read error, a warning is displayed
|
|
/// \note The storage type of the specified range will be changed to STT_VA.
|
|
|
|
idaman int ida_export file2base(
|
|
linput_t *li,
|
|
qoff64_t pos,
|
|
ea_t ea1,
|
|
ea_t ea2,
|
|
int patchable);
|
|
|
|
#define FILEREG_PATCHABLE 1 ///< means that the input file may be
|
|
///< patched (i.e. no compression,
|
|
///< no iterated data, etc)
|
|
#define FILEREG_NOTPATCHABLE 0 ///< the data is kept in some encoded
|
|
///< form in the file.
|
|
|
|
|
|
/// Load database from the memory.
|
|
/// This function works for wide byte processors too.
|
|
/// \param memptr pointer to buffer with bytes
|
|
/// \param ea1,ea2 range of destination linear addresses
|
|
/// \param fpos position in the input file the data is taken from.
|
|
/// if == -1, then no file position correspond to the data.
|
|
/// \return 1 always
|
|
/// \note The storage type of the specified range will be changed to STT_VA.
|
|
|
|
idaman int ida_export mem2base(const void *memptr, ea_t ea1, ea_t ea2, qoff64_t fpos);
|
|
|
|
|
|
/// Unload database to a binary file.
|
|
/// This function works for wide byte processors too.
|
|
/// \param fp pointer to file
|
|
/// \param pos position in the file
|
|
/// \param ea1,ea2 range of source linear addresses
|
|
/// \return 1-ok(always), write error leads to immediate exit
|
|
|
|
idaman int ida_export base2file(FILE *fp, qoff64_t pos, ea_t ea1, ea_t ea2);
|
|
|
|
|
|
/// Extract a module for an archive file.
|
|
/// Parse an archive file, show the list of modules to the user, allow him to
|
|
/// select a module, extract the selected module to a file (if the extract module
|
|
/// is an archive, repeat the process).
|
|
/// This function can handle ZIP, AR, AIXAR, OMFLIB files.
|
|
/// The temporary file will be automatically deleted by IDA at the end.
|
|
/// \param[in,out] filename in: input file.
|
|
/// out: name of the selected module.
|
|
/// \param bufsize size of the buffer with 'filename'
|
|
/// \param[out] temp_file_ptr will point to the name of the file that
|
|
/// contains the extracted module
|
|
/// \param is_remote is the input file remote?
|
|
/// \retval true ok
|
|
/// \retval false something bad happened (error message has been displayed to the user)
|
|
|
|
idaman bool ida_export extract_module_from_archive(
|
|
char *filename,
|
|
size_t bufsize,
|
|
char **temp_file_ptr,
|
|
bool is_remote);
|
|
|
|
|
|
/// Add long comment at \inf{min_ea}.
|
|
/// - Input file: ....
|
|
/// - File format: ....
|
|
///
|
|
/// This function should be called only from the loader to describe the input file.
|
|
|
|
idaman void ida_export create_filename_cmt(void);
|
|
|
|
|
|
/// Get the input file type.
|
|
/// This function can recognize libraries and zip files.
|
|
|
|
idaman filetype_t ida_export get_basic_file_type(linput_t *li);
|
|
|
|
|
|
/// Get name of the current file type.
|
|
/// The current file type is kept in \inf{filetype}.
|
|
/// \param buf buffer for the file type name
|
|
/// \param bufsize its size
|
|
/// \return size of answer, this function always succeeds
|
|
|
|
idaman size_t ida_export get_file_type_name(char *buf, size_t bufsize);
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Work with IDS files: read and use information from them
|
|
//
|
|
|
|
/// See ::importer_t
|
|
struct impinfo_t
|
|
{
|
|
const char *dllname;
|
|
void (idaapi*func)(uval_t num, const char *name, uval_t node);
|
|
uval_t node;
|
|
};
|
|
|
|
|
|
/// Callback for checking dll module - passed to import_module().
|
|
/// \param li pointer to input file
|
|
/// \param ii import info.
|
|
/// If the function finds that ii.dllname does not match
|
|
/// the module name passed to import_module(), it returns 0. \n
|
|
/// Otherwise it calls ii.func for each exported entry. \n
|
|
/// If ii.dllname==NULL then ii.func will be called
|
|
/// with num==0 and name==dllname.
|
|
/// \retval 0 dllname doesn't match, import_module() should continue
|
|
/// \retval 1 ok
|
|
|
|
typedef int idaapi importer_t(linput_t *li, impinfo_t *ii);
|
|
|
|
|
|
/// Find and import a DLL module.
|
|
/// This function adds information to the database (renames functions, etc).
|
|
/// \param module name of DLL
|
|
/// \param windir system directory with dlls
|
|
/// \param modnode node with information about imported entries.
|
|
/// either altval or supval arrays may be absent.
|
|
/// the node should never be deleted.
|
|
/// - imports by ordinals:
|
|
/// altval(ord) contains linear address
|
|
/// - imports by name:
|
|
/// supval(ea) contains the imported name
|
|
/// \param importer callback function (may be NULL) to check dll module
|
|
/// \param ostype type of operating system (subdir name).
|
|
/// NULL means the IDS directory itself (not recommended)
|
|
|
|
idaman void ida_export import_module(
|
|
const char *module,
|
|
const char *windir,
|
|
uval_t modnode,
|
|
importer_t *importer,
|
|
const char *ostype);
|
|
|
|
|
|
/// Load and apply IDS file.
|
|
/// This function loads the specified IDS file and applies it to the database.
|
|
/// If the program imports functions from a module with the same name
|
|
/// as the name of the ids file being loaded, then only functions from this
|
|
/// module will be affected. Otherwise (i.e. when the program does not import
|
|
/// a module with this name) any function in the program may be affected.
|
|
/// \param fname name of file to apply
|
|
/// \retval 1 ok
|
|
/// \retval 0 some error (a message is displayed).
|
|
/// if the ids file does not exist, no message is displayed
|
|
|
|
idaman int ida_export load_ids_module(char *fname);
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// DEFINITION OF PLUGIN MODULES
|
|
//----------------------------------------------------------------------
|
|
/// A plugin is a module in the plugins subdirectory that can perform
|
|
/// an action asked by the user. (usually via pressing a hotkey)
|
|
class plugin_t
|
|
{
|
|
public:
|
|
int version; ///< Should be equal to #IDP_INTERFACE_VERSION
|
|
int flags; ///< \ref PLUGIN_
|
|
/// \defgroup PLUGIN_ Plugin features
|
|
/// Used by plugin_t::flags
|
|
//@{
|
|
#define PLUGIN_MOD 0x0001 ///< Plugin changes the database.
|
|
///< IDA won't call the plugin if
|
|
///< the processor module prohibited any changes.
|
|
#define PLUGIN_DRAW 0x0002 ///< IDA should redraw everything after calling the plugin.
|
|
#define PLUGIN_SEG 0x0004 ///< Plugin may be applied only if the current address belongs to a segment
|
|
#define PLUGIN_UNL 0x0008 ///< Unload the plugin immediately after calling 'run'.
|
|
///< This flag may be set anytime.
|
|
///< The kernel checks it after each call to 'run'
|
|
///< The main purpose of this flag is to ease
|
|
///< the debugging of new plugins.
|
|
#define PLUGIN_HIDE 0x0010 ///< Plugin should not appear in the Edit, Plugins menu.
|
|
///< This flag is checked at the start.
|
|
#define PLUGIN_DBG 0x0020 ///< A debugger plugin. init() should put
|
|
///< the address of ::debugger_t to dbg.
|
|
#define PLUGIN_PROC 0x0040 ///< Load plugin when a processor module is loaded. (and keep it
|
|
///< until the processor module is unloaded)
|
|
#define PLUGIN_FIX 0x0080 ///< Load plugin when IDA starts and keep it in the memory until IDA stops
|
|
#define PLUGIN_MULTI 0x0100 ///< The plugin can work with multiple idbs in parallel.
|
|
///< init() returns a pointer to a plugmod_t object
|
|
///< run/term functions are not used.
|
|
///< Virtual functions of plugmod_t are used instead.
|
|
#define PLUGIN_SCRIPTED 0x8000 ///< Scripted plugin. Should not be used by plugins,
|
|
///< the kernel sets it automatically.
|
|
//@}
|
|
|
|
plugmod_t *(idaapi *init)(void); ///< Initialize plugin - returns a pointer to plugmod_t
|
|
#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_PLUGIN_RETURN_CODES__)
|
|
/// \defgroup PLUGIN_INIT Plugin initialization codes
|
|
/// Return values for plugin_t::init()
|
|
/// Deprecated, please update your plugins to use PLUGIN_MULTI.
|
|
//@{
|
|
#define PLUGIN_SKIP nullptr ///< Plugin doesn't want to be loaded
|
|
#define PLUGIN_OK ((plugmod_t *)1) ///< Plugin agrees to work with the current database.
|
|
///< It will be loaded as soon as the user presses the hotkey
|
|
#define PLUGIN_KEEP ((plugmod_t *)2) ///< Plugin agrees to work with the current database and wants to stay in the memory
|
|
//@}
|
|
#endif
|
|
|
|
void (idaapi *term)(void); ///< Terminate plugin. This function will be called
|
|
///< when the plugin is unloaded. May be NULL.
|
|
///< Must be NULL for PLUGIN_MULTI plugins
|
|
bool (idaapi *run)(size_t arg); ///< Invoke plugin.
|
|
///< Must be NULL for PLUGIN_MULTI plugins
|
|
const char *comment; ///< Long comment about the plugin.
|
|
///< it could appear in the status line
|
|
///< or as a hint
|
|
const char *help; ///< Multiline help about the plugin
|
|
const char *wanted_name; ///< The preferred short name of the plugin
|
|
const char *wanted_hotkey; ///< The preferred hotkey to run the plugin
|
|
};
|
|
|
|
#ifndef __X86__
|
|
CASSERT(sizeof(plugin_t) == 64);
|
|
#else
|
|
CASSERT(sizeof(plugin_t) == 36);
|
|
#endif
|
|
|
|
#if !defined(__KERNEL__) && !defined(PLUGIN_SUBMODULE)
|
|
idaman ida_module_data plugin_t PLUGIN; // (declaration for plugins)
|
|
#endif
|
|
|
|
/// Get plugin options from the command line.
|
|
/// If the user has specified the options in the -Oplugin_name:options
|
|
/// format, them this function will return the 'options' part of it
|
|
/// The 'plugin' parameter should denote the plugin name
|
|
/// Returns NULL if there we no options specified
|
|
|
|
idaman const char *ida_export get_plugin_options(const char *plugin);
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// Pattern to find plugin files
|
|
#ifdef __EA64__
|
|
# define PLUGIN_DLL "*64." DLLEXT
|
|
#else
|
|
# define PLUGIN_DLL "*." DLLEXT
|
|
#endif
|
|
|
|
|
|
// LOW LEVEL DLL LOADING FUNCTIONS
|
|
// Only the kernel should use these functions!
|
|
/// \cond
|
|
#define LNE_MAXSEG 10 // Max number of segments
|
|
|
|
#if 0
|
|
extern char dlldata[4096]; // Reserved place for DLL data
|
|
#define DLLDATASTART 0xA0 // Absolute offset of dlldata
|
|
extern char ldrdata[64]; // Reserved place for LOADER data
|
|
#define LDRDATASTART (DLLDATASTART+sizeof(dlldata)) // Absolute offset of ldrdata
|
|
#endif
|
|
|
|
struct idadll_t
|
|
{
|
|
void *dllinfo[LNE_MAXSEG];
|
|
void *entry; // first entry point of DLL
|
|
idadll_t(void) { dllinfo[0] = NULL; entry = NULL; }
|
|
bool is_loaded(void) const { return dllinfo[0] != NULL; }
|
|
};
|
|
|
|
#define MODULE_ENTRY_LOADER "LDSC"
|
|
#define MODULE_ENTRY_PLUGIN "PLUGIN"
|
|
#define MODULE_ENTRY_IDP "LPH"
|
|
|
|
int _load_core_module(
|
|
idadll_t *dllmem,
|
|
const char *file,
|
|
const char *entry);
|
|
// dllmem - allocated segments
|
|
// dos: segment 1 (data) isn't allocated
|
|
// Returns 0 - ok, else:
|
|
#define RE_NOFILE 1 /* No such file */
|
|
#define RE_NOTIDP 2 /* Not IDP file */
|
|
#define RE_NOPAGE 3 /* Can't load: bad segments */
|
|
#define RE_NOLINK 4 /* No linkage info */
|
|
#define RE_BADRTP 5 /* Bad relocation type */
|
|
#define RE_BADORD 6 /* Bad imported ordinal */
|
|
#define RE_BADATP 7 /* Bad relocation atype */
|
|
#define RE_BADMAP 8 /* DLLDATA offset is invalid */
|
|
|
|
void load_core_module_or_die(
|
|
idadll_t *dllmem,
|
|
const char *file,
|
|
const char *entry);
|
|
idaman bool ida_export load_core_module(
|
|
idadll_t *dllmem,
|
|
const char *file,
|
|
const char *entry);
|
|
|
|
idaman void ida_export free_dll(idadll_t *dllmem);
|
|
/// \endcond
|
|
|
|
/// Processor name
|
|
struct idp_name_t
|
|
{
|
|
qstring lname; ///< long processor name
|
|
qstring sname; ///< short processor name
|
|
bool hidden; ///< is hidden
|
|
idp_name_t() : hidden(false) {}
|
|
};
|
|
DECLARE_TYPE_AS_MOVABLE(idp_name_t);
|
|
typedef qvector<idp_name_t> idp_names_t; ///< vector of processor names
|
|
|
|
/// Processor module description
|
|
struct idp_desc_t
|
|
{
|
|
qstring path; ///< module file name
|
|
time_t mtime; ///< time of last modification
|
|
qstring family; ///< processor's family
|
|
idp_names_t names; ///< processor names
|
|
bool is_script; ///< the processor module is a script
|
|
bool checked; ///< internal, for cache management
|
|
idp_desc_t(): mtime(time_t(-1)), is_script(false), checked(false) {}
|
|
};
|
|
DECLARE_TYPE_AS_MOVABLE(idp_desc_t);
|
|
typedef qvector<idp_desc_t> idp_descs_t; ///< vector of processor module descriptions
|
|
|
|
|
|
/// Get IDA processor modules descriptions
|
|
|
|
idaman const idp_descs_t *ida_export get_idp_descs(void);
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// \def{IDP_DLL, Pattern to find idp files}
|
|
#ifdef __EA64__
|
|
# define IDP_DLL "*64." DLLEXT
|
|
#else
|
|
# define IDP_DLL "*." DLLEXT
|
|
#endif
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// Structure to store Plugin information
|
|
struct plugin_info_t
|
|
{
|
|
plugin_info_t *next; ///< next plugin information
|
|
char *path; ///< full path to the plugin
|
|
char *org_name; ///< original short name of the plugin
|
|
char *name; ///< short name of the plugin
|
|
///< it will appear in the menu
|
|
ushort org_hotkey; ///< original hotkey to run the plugin
|
|
ushort hotkey; ///< current hotkey to run the plugin
|
|
size_t arg; ///< argument used to call the plugin
|
|
plugin_t *entry; ///< pointer to the plugin if it is already loaded
|
|
idadll_t dllmem;
|
|
int flags; ///< a copy of plugin_t::flags
|
|
char *comment; ///< a copy of plugin_t::comment
|
|
};
|
|
|
|
|
|
/// Get pointer to the list of plugins. (some plugins might be listed several times
|
|
/// in the list - once for each configured argument)
|
|
|
|
idaman plugin_info_t *ida_export get_plugins(void);
|
|
|
|
|
|
/// Find a user-defined plugin and optionally load it.
|
|
/// \param name short plugin name without path and extension,
|
|
/// or absolute path to the file name
|
|
/// \param load_if_needed if the plugin is not present in the memory, try to load it
|
|
/// \return pointer to plugin description block
|
|
|
|
idaman plugin_t *ida_export find_plugin(const char *name, bool load_if_needed=false);
|
|
|
|
inline plugin_t *load_plugin(const char *name)
|
|
{
|
|
return find_plugin(name, true);
|
|
}
|
|
|
|
|
|
/// Run a loaded plugin with the specified argument.
|
|
/// \param ptr pointer to plugin description block
|
|
/// \param arg argument to run with
|
|
|
|
idaman bool ida_export run_plugin(const plugin_t *ptr, size_t arg);
|
|
|
|
|
|
/// Load & run a plugin
|
|
|
|
inline bool idaapi load_and_run_plugin(const char *name, size_t arg)
|
|
{
|
|
return run_plugin(load_plugin(name), arg);
|
|
}
|
|
|
|
|
|
/// Run a plugin as configured.
|
|
/// \param ptr pointer to plugin information block
|
|
|
|
idaman bool ida_export invoke_plugin(plugin_info_t *ptr);
|
|
|
|
|
|
/// Information for the user interface about available debuggers
|
|
struct dbg_info_t
|
|
{
|
|
plugin_info_t *pi;
|
|
struct debugger_t *dbg;
|
|
dbg_info_t(plugin_info_t *_pi, struct debugger_t *_dbg) : pi(_pi), dbg(_dbg) {}
|
|
};
|
|
DECLARE_TYPE_AS_MOVABLE(dbg_info_t);
|
|
|
|
|
|
/// Get information about available debuggers
|
|
|
|
idaman size_t ida_export get_debugger_plugins(const dbg_info_t **array);
|
|
|
|
|
|
/// Initialize plugins with the specified flag
|
|
|
|
idaman void ida_export init_plugins(int flag);
|
|
|
|
|
|
/// Terminate plugins with the specified flag
|
|
|
|
idaman void ida_export term_plugins(int flag);
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
/// Get offset in the input file which corresponds to the given ea.
|
|
/// If the specified ea can't be mapped into the input file offset,
|
|
/// return -1.
|
|
|
|
idaman qoff64_t ida_export get_fileregion_offset(ea_t ea);
|
|
|
|
|
|
/// Get linear address which corresponds to the specified input file offset.
|
|
/// If can't be found, return #BADADDR
|
|
|
|
idaman ea_t ida_export get_fileregion_ea(qoff64_t offset);
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
/// Generate an exe file (unload the database in binary form).
|
|
/// \return fp the output file handle. if fp == NULL then return:
|
|
/// - 1: can generate an executable file
|
|
/// - 0: can't generate an executable file
|
|
/// \retval 1 ok
|
|
/// \retval 0 failed
|
|
|
|
idaman int ida_export gen_exe_file(FILE *fp);
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
/// Reload the input file.
|
|
/// This function reloads the byte values from the input file.
|
|
/// It doesn't modify the segmentation, names, comments, etc.
|
|
/// \param file name of the input file. if file == NULL then returns:
|
|
/// - 1: can reload the input file
|
|
/// - 0: can't reload the input file
|
|
/// \param is_remote is the file located on a remote computer with
|
|
/// the debugger server?
|
|
/// \return success
|
|
|
|
idaman bool ida_export reload_file(const char *file, bool is_remote);
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// S N A P S H O T F U N C T I O N S
|
|
|
|
/// Maximum database snapshot description length
|
|
#define MAX_DATABASE_DESCRIPTION 128
|
|
|
|
class snapshot_t;
|
|
typedef qvector<snapshot_t *> snapshots_t; ///< vector of database snapshots
|
|
|
|
/// Snapshot attributes
|
|
class snapshot_t
|
|
{
|
|
private:
|
|
snapshot_t &operator=(const snapshot_t &);
|
|
snapshot_t(const snapshot_t &);
|
|
|
|
int compare(const snapshot_t &r) const
|
|
{
|
|
return ::compare(id, r.id);
|
|
}
|
|
|
|
public:
|
|
qtime64_t id; ///< snapshot ID. This value is computed using qgettimeofday()
|
|
uint16 flags; ///< \ref SSF_
|
|
/// \defgroup SSF_ Snapshot flags
|
|
/// Used by snapshot_t::flags
|
|
//@{
|
|
#define SSF_AUTOMATIC 0x0001 ///< automatic snapshot
|
|
//@}
|
|
char desc[MAX_DATABASE_DESCRIPTION]; ///< snapshot description
|
|
char filename[QMAXPATH]; ///< snapshot file name
|
|
snapshots_t children; ///< snapshot children
|
|
DEFINE_MEMORY_ALLOCATION_FUNCS()
|
|
DECLARE_COMPARISON_OPERATORS(snapshot_t)
|
|
void clear()
|
|
{
|
|
for ( snapshots_t::iterator p=children.begin();
|
|
p != children.end();
|
|
++p )
|
|
{
|
|
delete *p;
|
|
}
|
|
children.clear();
|
|
}
|
|
|
|
snapshot_t(): id(0), flags(0)
|
|
{
|
|
filename[0] = desc[0] = '\0';
|
|
}
|
|
|
|
~snapshot_t()
|
|
{
|
|
clear();
|
|
}
|
|
};
|
|
DECLARE_TYPE_AS_MOVABLE(snapshot_t);
|
|
|
|
//------------------------------------------------------------------------
|
|
/// Build the snapshot tree.
|
|
/// \param root snapshot root that will contain the snapshot tree elements.
|
|
/// \return success
|
|
|
|
idaman bool ida_export build_snapshot_tree(snapshot_t *root);
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
/// Update the snapshot attributes.
|
|
/// \note only the snapshot description can be updated.
|
|
/// \param filename snapshot file name or NULL for the current database
|
|
/// \param root snapshot root (returned from build_snapshot_tree())
|
|
/// \param attr snapshot instance containing the updated attributes
|
|
/// \param uf \ref SSUF_
|
|
/// \return success
|
|
idaman bool ida_export update_snapshot_attributes(
|
|
const char *filename,
|
|
const snapshot_t *root,
|
|
const snapshot_t *attr,
|
|
int uf);
|
|
|
|
/// \defgroup SSUF_ Snapshot update flags
|
|
/// Passed as 'uf' parameter to update_snapshot_attributes()
|
|
//@{
|
|
#define SSUF_DESC 0x00000001 ///< Update the description
|
|
#define SSUF_PATH 0x00000002 ///< Update the path
|
|
#define SSUF_FLAGS 0x00000004 ///< Update the flags
|
|
//@}
|
|
|
|
//------------------------------------------------------------------------
|
|
/// Visit the snapshot tree.
|
|
/// \param root snapshot root to start the enumeration from
|
|
/// \param callback callback called for each child. return 0 to continue enumeration
|
|
/// and non-zero to abort enumeration
|
|
/// \param ud user data. will be passed back to the callback
|
|
/// \return true-ok, false-failed
|
|
|
|
idaman int ida_export visit_snapshot_tree(
|
|
snapshot_t *root,
|
|
int (idaapi *callback)(snapshot_t *ss, void *ud),
|
|
void *ud=NULL);
|
|
|
|
|
|
/// Flush buffers to the disk
|
|
|
|
idaman int ida_export flush_buffers(void);
|
|
|
|
|
|
/// Is the database considered as trusted?
|
|
|
|
idaman bool ida_export is_trusted_idb(void);
|
|
|
|
//------------------------------------------------------------------------
|
|
/// Save current database using a new file name.
|
|
/// \param outfile output database file name
|
|
/// \param flags \ref DBFL_
|
|
/// \param root optional: snapshot tree root.
|
|
/// \param attr optional: snapshot attributes
|
|
/// \note when both root and attr are not NULL then the snapshot
|
|
/// attributes will be updated, otherwise the snapshot attributes
|
|
/// will be inherited from the current database.
|
|
/// \return success
|
|
|
|
idaman bool ida_export save_database(
|
|
const char *outfile,
|
|
uint32 flags,
|
|
const snapshot_t *root = NULL,
|
|
const snapshot_t *attr = NULL);
|
|
|
|
/// \defgroup DBFL_ Database flags
|
|
/// Used to manage saving/closing of a database
|
|
//@{
|
|
#define DBFL_KILL 0x01 ///< delete unpacked database
|
|
#define DBFL_COMP 0x02 ///< collect garbage
|
|
#define DBFL_BAK 0x04 ///< create backup file (if !DBFL_KILL)
|
|
#define DBFL_TEMP 0x08 ///< temporary database
|
|
//@}
|
|
|
|
/// Get the current database flag
|
|
/// \param dbfl flag \ref DBFL_
|
|
/// \returns the state of the flag (set or cleared)
|
|
|
|
idaman bool ida_export is_database_flag(uint32 dbfl);
|
|
|
|
/// Set or clear database flag
|
|
/// \param dbfl flag \ref DBFL_
|
|
/// \param cnd set if true or clear flag otherwise
|
|
|
|
idaman void ida_export set_database_flag(uint32 dbfl, bool cnd=true);
|
|
inline void clr_database_flag(uint32 dbfl) { set_database_flag(dbfl, false); }
|
|
|
|
/// Is a temporary database?
|
|
inline bool is_temp_database(void) { return is_database_flag(DBFL_TEMP); }
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
/// \defgroup PATH_TYPE_ Types of the file pathes
|
|
//@{
|
|
enum path_type_t
|
|
{
|
|
PATH_TYPE_CMD, ///< full path to the file specified in the command line
|
|
PATH_TYPE_IDB, ///< full path of IDB file
|
|
PATH_TYPE_ID0, ///< full path of ID0 file
|
|
};
|
|
//@}
|
|
|
|
/// Get the file path
|
|
/// \param pt file path type \ref PATH_TYPE_
|
|
/// \returns file path, never returns NULL
|
|
idaman const char *ida_export get_path(path_type_t pt);
|
|
|
|
/// Set the file path
|
|
/// \param pt file path type \ref PATH_TYPE_
|
|
/// \param path new file path,
|
|
/// use NULL or empty string to clear the file path
|
|
idaman void ida_export set_path(path_type_t pt, const char *path);
|
|
|
|
|
|
/// Check the file extension
|
|
/// \returns true if it is the reserved extension
|
|
idaman bool ida_export is_database_ext(const char *ext);
|
|
|
|
|
|
/// Get the value of the ELF_DEBUG_FILE_DIRECTORY configuration
|
|
/// directive.
|
|
idaman const char *ida_export get_elf_debug_file_directory();
|
|
|
|
/// \cond
|
|
|
|
#endif
|