Repository URL to install this package:
Version:
9.0~241217-2.fc42 ▾
|
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2024 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 the #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 == nullptr, then this function returns:
/// - 0: can't create file of this type
/// - 1: ok, can create file of this type
///
/// If fp != nullptr, 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 nullptr
/// \param errbuf error message if 0 is returned,
/// may be nullptr
/// \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 == nullptr, 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=nullptr, ...)
{
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 "*." DLLEXT
#else
# define LOADER_DLL "*32." 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} != nullptr
/// 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 'loader' is a 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=nullptr);
//--------------------------------------------------------------------------
/// 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==nullptr 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
/// please use set_import_ordinal()/set_import_name()
/// to work with MODNODE
/// \param importer callback function (may be nullptr) to check dll module
/// \param ostype type of operating system (subdir name).
/// nullptr 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);
/// Set information about the ordinal import entry.
/// This function performs 'modnode.altset(ord, ea2node(ea));'
/// \param modnode node with information about imported entries
/// \param ea linear address of the entry
/// \param ord ordinal number of the entry
idaman void ida_export set_import_ordinal(
uval_t modnode,
ea_t ea,
uval_t ord);
/// Set information about the named import entry.
/// This function performs 'modnode.supset_ea(ea, name);'
/// \param modnode node with information about imported entries
/// \param ea linear address of the entry
/// \param name name of the entry
idaman void ida_export set_import_name(
uval_t modnode,
ea_t ea,
const char *name);
/// 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 nullptr.
///< Must be nullptr for PLUGIN_MULTI plugins
bool (idaapi *run)(size_t arg); ///< Invoke plugin.
///< Must be nullptr 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 nullptr 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 "*." DLLEXT
#else
# define PLUGIN_DLL "*32." 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] = nullptr; entry = nullptr; }
bool is_loaded(void) const { return dllinfo[0] != nullptr; }
};
#define MODULE_ENTRY_LOADER "LDSC" ///< name of loader entry point
#define MODULE_ENTRY_PLUGIN "PLUGIN" ///< name of plugin entry point
#define MODULE_ENTRY_IDP "LPH" ///< name of processor module entry point
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 "*." DLLEXT
#else
# define IDP_DLL "*32." 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
qstring idaplg_name; ///< "name" provided by ida-plugin.json or basename of path (without extension)
plugin_info_t()
{
memset(this, 0, sizeof(*this));
}
};
/// 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 == nullptr 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 == nullptr 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 = 0; ///< snapshot ID. This value is computed using qgettimeofday()
uint16 flags = 0; ///< \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()
{
desc[0] = '\0';
filename[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 nullptr 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=nullptr);
/// 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; nullptr means the current path
/// \param flags \ref DBFL_; -1 means the current flags
/// \param root optional: snapshot tree root.
/// \param attr optional: snapshot attributes
/// \note when both root and attr are not nullptr 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=nullptr,
uint32 flags=-1,
const snapshot_t *root = nullptr,
const snapshot_t *attr = nullptr);
/// \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 nullptr
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 nullptr 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