Latest available version: IDA and decompilers v8.4.240320sp1 see all releases
Hex-Rays logo State-of-the-art binary code analysis tools
email icon
merge.hpp File Reference

Merge functionality. More...

Classes

class  merge_data_t
 class to contain public info about the merge process More...
 
struct  merge_data_t::item_block_locator_t
 several items can be grouped into a block. More...
 
struct  merge_handler_params_t
 Merge handler parameters. More...
 
struct  moddata_diff_helper_t
 helper class for module data diff source More...
 
struct  merge_node_helper_t
 abstract adapter to provide access to non-standard netnode array entries More...
 
struct  merge_node_info_t
 field descriptor used to organize merging of a netnode array More...
 
struct  merge_node_info2_t
 

Macros

#define MH_LISTEN   0x00000001
 merge handler will receive merge events
 
#define MH_TERSE   0x00000002
 do not display equal lines in the merge results table
 
#define MH_UI_NODETAILS   0x00000100
 ida will not show the diffpos details
 
#define MH_UI_COMPLEX   0x00000200
 diffpos details won't be displayed in the diffpos chooser
 
#define MH_UI_DP_NOLINEDIFF   0x00000400
 Detail pane: do not show differences inside the line.
 
#define MH_UI_DP_SHORTNAME   0x00000800
 Detail pane: use the first part of a complex diffpos name as the tree node name.
 
#define MH_UI_INDENT   0x00001000
 preserve indent for diffpos name in diffpos chooser
 
#define MH_UI_SPLITNAME   0x00800000
 ida will split the diffpos name by 7-bit ASCII char to create chooser columns
 
#define MH_UI_CHAR_MASK   0x007F0000
 7-bit ASCII split character
 
#define MH_UI_DEF_CHAR(v)   ((((v) & 0x7F) << 16) | MH_UI_SPLITNAME)
 define split char
 
#define MH_UI_COMMANAME   MH_UI_DEF_CHAR(',')
 ida will split the diffpos name by ',' to create chooser columns
 
#define MH_UI_COLONNAME   MH_UI_DEF_CHAR(':')
 ida will split the diffpos name by ':' to create chooser columns
 
#define MH_DUMMY   0x80000000
 dummy entry - just to fill an array slot
 
#define IDI_FLDENTRY(struc, field, mask, valmap, name)
 idbattr_info_t entry for scalar structure field More...
 
#define IDI_FLDQSTR(struc, field, name)    { name, qoffsetof(struc, field), 0, 0, 0, nullptr, nullptr, IDI_STRUCFLD|IDI_QSTRING }
 idbattr_info_t entry for qstring structure field
 
#define IDI_ALTENTRY(altidx, tag, width, mask, valmap, name)
 idbattr_info_t entry for scalar node altval More...
 
#define IDI_HASHENTRY(hashname, tag, width, mask, flag, valmap, name)
 idbattr_info_t entry for named node hash entry More...
 
#define IDI_SUPSTR(altidx, tag, name)    { name, uintptr_t(altidx), 0, 0, tag, nullptr, nullptr, IDI_SUPVAL|IDI_CSTR }
 idbattr_info_t entry for node supstr
 
#define IDI_DEVICE_ENTRY   IDI_SUPSTR(-1, stag, "device")
 standard idbattr_info_t entry for 'device' (to be used in processor modules)
 
#define MNI_ENTRY(tag, flags, name, helper)    { name, tag, NDS_MAP_IDX|NDS_EV_RANGE|(flags), helper }
 merge_node_info_t entry for node value
 
#define MNI_FUNCENTRY(tag, flags, name)    MNI_ENTRY(tag, NDS_EV_FUNC|(flags), name, nullptr)
 merge_node_info_t entry to be used inside functions only
 
#define MNI_STDENTRY(tag, flags, name)   MNI_ENTRY(tag, flags, name, nullptr)
 merge_node_info_t entry for node with default representation (no helper)
 

Typedefs

using merge_handlers_t = qvector< merge_handler_t * >
 
typedef merge_node_helper_tmerge_node_helper_creator_t(merge_data_t &md, int dbctx_id)
 
using merge_node_hlpfunc_creator_t = std::function< merge_node_helper_creator_t >
 

Enumerations

enum  merge_kind_t {
  MERGE_KIND_NETNODE , MERGE_KIND_AUTOQ , MERGE_KIND_INF , MERGE_KIND_ENCODINGS ,
  MERGE_KIND_ENCODINGS2 , MERGE_KIND_SCRIPTS2 , MERGE_KIND_SCRIPTS , MERGE_KIND_CUSTDATA ,
  MERGE_KIND_ENUMS , MERGE_KIND_STRUCTS , MERGE_KIND_TILS , MERGE_KIND_TINFO ,
  MERGE_KIND_STRMEM , MERGE_KIND_UDTMEM , MERGE_KIND_GHSTRCMT , MERGE_KIND_STRMEMCMT ,
  MERGE_KIND_SELECTORS , MERGE_KIND_STT , MERGE_KIND_SEGMENTS , MERGE_KIND_SEGGRPS ,
  MERGE_KIND_SEGREGS , MERGE_KIND_ORPHANS , MERGE_KIND_BYTEVAL , MERGE_KIND_FIXUPS ,
  MERGE_KIND_MAPPING , MERGE_KIND_EXPORTS , MERGE_KIND_IMPORTS , MERGE_KIND_PATCHES ,
  MERGE_KIND_FLAGS , MERGE_KIND_EXTRACMT , MERGE_KIND_AFLAGS_EA , MERGE_KIND_IGNOREMICRO ,
  MERGE_KIND_FILEREGIONS , MERGE_KIND_HIDDENRANGES , MERGE_KIND_SOURCEFILES , MERGE_KIND_FUNC ,
  MERGE_KIND_FRAMEMGR , MERGE_KIND_FRAME , MERGE_KIND_STKPNTS , MERGE_KIND_FLOWS ,
  MERGE_KIND_CREFS , MERGE_KIND_DREFS , MERGE_KIND_BPTS , MERGE_KIND_WATCHPOINTS ,
  MERGE_KIND_BOOKMARKS , MERGE_KIND_TRYBLKS , MERGE_KIND_DIRTREE , MERGE_KIND_VFTABLES ,
  MERGE_KIND_SIGNATURES , MERGE_KIND_PROBLEMS , MERGE_KIND_UI , MERGE_KIND_DEKSTOPS ,
  MERGE_KIND_NOTEPAD , MERGE_KIND_LOADER , MERGE_KIND_DEBUGGER , MERGE_KIND_DBG_MEMREGS ,
  MERGE_KIND_LUMINA , MERGE_KIND_LAST , MERGE_KIND_END = merge_kind_t(-2) , MERGE_KIND_NONE = merge_kind_t(-1)
}
 Kinds of merge handlers. More...
 
enum  nds_flags_t {
  NDS_IS_BOOL = 0x0001 , NDS_IS_EA = 0x0002 , NDS_IS_RELATIVE = 0x0004 , NDS_IS_STR = 0x0008 ,
  NDS_SUPVAL = 0x0010 , NDS_BLOB = 0x0020 , NDS_EV_RANGE = 0x0040 , NDS_EV_FUNC = 0x0080 ,
  NDS_MAP_IDX = 0x0100 , NDS_MAP_VAL = 0x0200 , NDS_VAL8 = 0x1000 , NDS_INC = 0x2000 ,
  NDS_UI_ND = 0x4000
}
 netnode value modificators (to be used in nodeval_diff_source, see below) More...
 

Functions

idaman bool ida_export is_diff_merge_mode ()
 Return TRUE if IDA is running in diff mode (MERGE_POLICY_MDIFF/MERGE_POLICY_VDIFF)
 
idaman merge_handler_t *ida_export create_nodeval_merge_handler (const merge_handler_params_t &mhp, const char *label, int moddata_id, const char *nodename, uchar tag, uint32 nds_flags, merge_node_hlpfunc_creator_t nhc=nullptr, bool skip_empty_nodes=true)
 Create a merge handler for netnode scalar/string values. More...
 
idaman merge_handler_t *ida_export create_nodeval_merge_handler2 (const merge_handler_params_t &mhp, const char *label, int moddata_id, const char *nodename, uchar tag, uint32 nds_flags, merge_node_helper_t *node_helper=nullptr, bool skip_empty_nodes=true)
 
idaman void ida_export create_nodeval_merge_handlers (merge_handlers_t *out, const merge_handler_params_t &mhp, int moddata_id, const char *nodename, const merge_node_info_t *valdesc, size_t nvals, bool skip_empty_nodes=true)
 Create a serie of merge handlers for netnode scalar/string values (call create_nodeval_merge_handler() for each member of VALDESC) More...
 
idaman void ida_export create_nodeval_merge_handlers2 (merge_handlers_t *out, const merge_handler_params_t &mhp, int moddata_id, const char *nodename, const merge_node_info2_t *valdesc, size_t nvals, bool skip_empty_nodes=true)
 
idaman void ida_export destroy_moddata_merge_handlers (int data_id)
 
idaman ssize_t ida_export get_ea_diffpos_name (qstring *out, ea_t ea)
 Get nice name for EA diffpos. More...
 

Detailed Description

Merge functionality.

NOTE: this functionality is available in IDA Teams (not IDA Pro)

There are 3 databases involved in merging: base_idb, local_db, and remote_idb.

  • base_idb: the common base ancestor of 'local_db' and 'remote_db'. in the UI this database is located in the middle.
  • local_idb: local database that will contain the result of the merging. in the UI this database is located on the left.
  • remote_idb: remote database that will merge into local_idb. It may reside locally on the current computer, despite its name. in the UI this database is located on the right. base_idb and remote_idb are opened for reading only. base_idb may be absent, in this case a 2-way merging is performed.

Conflicts can be resolved automatically or interactively. The automatic resolving scores the conflicting blocks and takes the better one. The interactive resolving displays the full rendered contents side by side, and expects the user to select the better side for each conflict.

Since IDB files contain various kinds of information, there are many merging phases. The entire list can be found in merge.cpp. Below are just some selected examples:

  • merge global database settings (inf and other global vars)
  • merge segmentation and changes to the database bytes
  • merge various lists: exports, imports, loaded tils, etc
  • merge names, functions, function frames
  • merge debugger settings, breakpoints
  • merge struct/enum views
  • merge local type libraries
  • merge the disassembly items (i.e. the segment contents) this includes operand types, code/data separation, etc
  • merge plugin specific info like decompiler types, dwarf mappings, etc

To unify UI elements of each merge phase, we use merger views:

  • A view that consists of 2 or 3 panes: left (local_idb) and right (remote_idb). The common base is in the middle, if present.
  • Rendering of the panes depends on the phase, different phases show different contents.
  • The conflicts are highlighted by a colored background. Also, the detail pane can be consulted for additional info.
  • The user can select a conflict (or a bunch of conflicts) and say "use this block".
  • The user can browse the panes as he wishes. He will not be forced to handle conflicts in any particular order. However, once he finishes working with a merge handler and proceeds to the next one, he cannot go back.
  • Scrolling the left pane will synchronously scroll the right pane and vice versa.
  • There are the navigation commands like "go to the prev/next conflict"
  • The number of remaining conflicts to resolve is printed in the "Progress" chooser.
  • The user may manually modify local database inside the merger view. For that he may use the regular hotkeys. However, editing the database may lead to new conflicts, so we better restrict the available actions to some reasonable minimum. Currently, this is not implemented.

IDA works in a new "merge" mode during merging. In this mode most events are not generated. We forbid them to reduce the risk that a rogue third-party plugin that is not aware of the "merge" mode would spoil something.

For example, normally renaming a function causes a cascade of events and may lead to other database modifications. Some of them may be desired, some - not. Since there are some undesired events, it is better to stop generating them. However, some events are required to render the disassembly listing. For example, ev_ana_insn, av_out_insn. This is why some events are still generated in the "merge" mode.

To let processor modules and plugins merge their data, we introduce a new event: ev_create_merge_handlers. It is generated immediately after opening all three idbs. The interested modules should react to this event by creating new merge handlers, if they need them.

While the kernel can create arbitrary merge handlers, modules can create only the standard ones returned by:

create_nodeval_merge_handler() create_nodeval_merge_handlers() create_std_modmerge_handlers()

We do not document merge_handler_t because once a merge handler is created, it is used exclusively by the kernel.

See mergemod.hpp for more information about the merge mode for modules.

Macro Definition Documentation

◆ IDI_FLDENTRY

#define IDI_FLDENTRY (   struc,
  field,
  mask,
  valmap,
  name 
)
Value:
{ name, /* field description */ \
qoffsetof(struc, field), /* offset */ \
sizeof(struc::field), /* width */ \
mask, /* bitmask */ \
0, /* tag (for node values only) */ \
valmap, /* vmap */ \
nullptr, /* individual_node */ \
IDI_STRUCFLD|IDI_SCALAR } /* flags */
#define IDI_SCALAR
scalar value (default)
Definition: ida.hpp:1463

idbattr_info_t entry for scalar structure field

◆ IDI_ALTENTRY

#define IDI_ALTENTRY (   altidx,
  tag,
  width,
  mask,
  valmap,
  name 
)
Value:
{ name, /* field description */ \
uintptr_t(altidx), /* altval index */ \
width, /* width */ \
mask, /* bitmask */ \
tag, /* tag (for node values only) */ \
valmap, /* vmap */ \
nullptr, /* individual_node */ \
IDI_ALTVAL|IDI_SCALAR } /* flags */

idbattr_info_t entry for scalar node altval

◆ IDI_HASHENTRY

#define IDI_HASHENTRY (   hashname,
  tag,
  width,
  mask,
  flag,
  valmap,
  name 
)
Value:
{ name, /* field description */ \
uintptr_t(hashname), /* hash name */ \
width, /* width */ \
mask, /* bitmask */ \
tag, /* tag (for node values only) */ \
valmap, /* vmap */ \
nullptr, /* individual_node */ \
IDI_HASH|(flag) } /* flags */

idbattr_info_t entry for named node hash entry

Enumeration Type Documentation

◆ merge_kind_t

Kinds of merge handlers.

Enumerator
MERGE_KIND_NETNODE 

netnode (no merging, to be used in idbunits)

MERGE_KIND_AUTOQ 

auto queues

MERGE_KIND_INF 

merge the inf variable (global settings)

MERGE_KIND_ENCODINGS 

merge encodings

MERGE_KIND_ENCODINGS2 

merge default encodings

MERGE_KIND_SCRIPTS2 

merge scripts common info

MERGE_KIND_SCRIPTS 

merge scripts

MERGE_KIND_CUSTDATA 

merge custom data type and formats

MERGE_KIND_ENUMS 

merge enums

MERGE_KIND_STRUCTS 

merge structs (globally: add/delete structs entirely)

MERGE_KIND_TILS 

merge type libraries

MERGE_KIND_TINFO 

merge tinfo

MERGE_KIND_STRMEM 

merge struct members

MERGE_KIND_UDTMEM 

merge UDT members (local types)

MERGE_KIND_GHSTRCMT 

merge ghost structure comment

MERGE_KIND_STRMEMCMT 

merge member comments for ghost struc

MERGE_KIND_SELECTORS 

merge selectors

MERGE_KIND_STT 

merge flag storage types

MERGE_KIND_SEGMENTS 

merge segments

MERGE_KIND_SEGGRPS 

merge segment groups

MERGE_KIND_SEGREGS 

merge segment registers

MERGE_KIND_ORPHANS 

merge orphan bytes

MERGE_KIND_BYTEVAL 

merge byte values

MERGE_KIND_FIXUPS 

merge fixups

MERGE_KIND_MAPPING 

merge manual memory mapping

MERGE_KIND_EXPORTS 

merge exports

MERGE_KIND_IMPORTS 

merge imports

MERGE_KIND_PATCHES 

merge patched bytes

MERGE_KIND_FLAGS 

merge flags64_t

MERGE_KIND_EXTRACMT 

merge extra next or prev lines

MERGE_KIND_AFLAGS_EA 

merge aflags for mapped EA

MERGE_KIND_IGNOREMICRO 

IM ("$ ignore micro") flags.

MERGE_KIND_FILEREGIONS 

merge fileregions

MERGE_KIND_HIDDENRANGES 

merge hidden ranges

MERGE_KIND_SOURCEFILES 

merge source files ranges

MERGE_KIND_FUNC 

merge func info

MERGE_KIND_FRAMEMGR 

merge frames (globally: add/delete frames entirely)

MERGE_KIND_FRAME 

merge function frame info (frame members)

MERGE_KIND_STKPNTS 

merge SP change points

MERGE_KIND_FLOWS 

merge flows

MERGE_KIND_CREFS 

merge crefs

MERGE_KIND_DREFS 

merge drefs

MERGE_KIND_BPTS 

merge breakpoints

MERGE_KIND_WATCHPOINTS 

merge watchpoints

MERGE_KIND_BOOKMARKS 

merge bookmarks

MERGE_KIND_TRYBLKS 

merge try blocks

MERGE_KIND_DIRTREE 

merge std dirtrees

MERGE_KIND_VFTABLES 

merge vftables

MERGE_KIND_SIGNATURES 

signatures

MERGE_KIND_PROBLEMS 

problems

MERGE_KIND_UI 

UI.

MERGE_KIND_DEKSTOPS 

dekstops

MERGE_KIND_NOTEPAD 

notepad

MERGE_KIND_LOADER 

loader data

MERGE_KIND_DEBUGGER 

debugger data

MERGE_KIND_DBG_MEMREGS 

manual memory regions (debugger)

MERGE_KIND_LUMINA 

lumina function metadata

MERGE_KIND_LAST 

last predefined merge handler type.

please note that there can be more merge handler types, registered by plugins and processor modules.

MERGE_KIND_END 

insert to the end of handler list, valid for merge_handler_params_t::insert_after

◆ nds_flags_t

netnode value modificators (to be used in nodeval_diff_source, see below)

Enumerator
NDS_IS_BOOL 

boolean value

NDS_IS_EA 

EA value.

NDS_IS_RELATIVE 

value is relative to index (stored as delta)

NDS_IS_STR 

string value

NDS_SUPVAL 

stored as netnode supvals (not scalar)

NDS_BLOB 

stored as netnode blobs

NDS_EV_RANGE 

enable default handling of mev_modified_ranges, mev_deleting_segm

NDS_EV_FUNC 

enable default handling of mev_added_func/mev_deleting_func

NDS_MAP_IDX 

apply ea2node() to index (==NETMAP_IDX)

NDS_MAP_VAL 

apply ea2node() to value.

Along with NDS_INC it gives effect of NETMAP_VAL, examples: altval_ea : NDS_MAP_IDX charval : NDS_VAL8 charval_ea: NDS_MAP_IDX|NDS_VAL8 eaget : NDS_MAP_IDX|NDS_MAP_VAL|NDS_INC

NDS_VAL8 

use 8-bit values (==NETMAP_V8)

NDS_INC 

stored value is incremented (scalars only)

NDS_UI_ND 

UI: no need to show diffpos detail pane, MH_UI_NODETAILS, make sense if merge_node_helper_t is used.

Function Documentation

◆ create_nodeval_merge_handler()

idaman merge_handler_t *ida_export create_nodeval_merge_handler ( const merge_handler_params_t mhp,
const char *  label,
int  moddata_id,
const char *  nodename,
uchar  tag,
uint32  nds_flags,
merge_node_hlpfunc_creator_t  nhc = nullptr,
bool  skip_empty_nodes = true 
)

Create a merge handler for netnode scalar/string values.

Parameters
mhpmerging parameters
labelhandler short name (to be be appended to mhp.label)
moddata_idmodule data ID (to be passed to get_module_data)
nodenamenetnode name
taga tag used to access values in the netnode
nds_flagsnetnode value attributes (a combination of nds_flags_t)
nhca factory to create instances of merge_node_helper_t
skip_empty_nodesdo not create handler in case of empty netnode
Returns
diff source object (normally should be attahced to a merge handler)

◆ create_nodeval_merge_handlers()

idaman void ida_export create_nodeval_merge_handlers ( merge_handlers_t out,
const merge_handler_params_t mhp,
int  moddata_id,
const char *  nodename,
const merge_node_info_t valdesc,
size_t  nvals,
bool  skip_empty_nodes = true 
)

Create a serie of merge handlers for netnode scalar/string values (call create_nodeval_merge_handler() for each member of VALDESC)

Parameters
out[out] created handlers will be placed here
mhpmerging parameters
moddata_idmodule data ID (to be passed to get_module_data)
nodenamenetnode name
valdescarray of handler descriptions
nvalsnumber of members in VALDESC
skip_empty_nodesdo not create handlers for empty netnodes
Returns
diff source object (normally should be attahced to a merge handler)

◆ get_ea_diffpos_name()

idaman ssize_t ida_export get_ea_diffpos_name ( qstring out,
ea_t  ea 
)

Get nice name for EA diffpos.

Parameters
eadiffpos
[out]outnice name
Note
See also
get_nice_colored_name