| IDA SDK

Classes | Functions | Macros | Typedefs | Enumerations
merge.hpp File Reference

## 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.

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

## 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...

## 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_t * | merge_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...

## 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 */
IDI_SCALAR
#define IDI_SCALAR
scalar value (default)
Definition: ida.hpp:1469

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

enum 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

enum 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

  mhp | merging parameters
  label | handler short name (to be be appended to mhp.label)
  moddata_id | module data ID (to be passed to get_module_data)
  nodename | netnode name
  tag | a tag used to access values in the netnode
  nds_flags | netnode value attributes (a combination of nds_flags_t)
  nhc | a factory to create instances of merge_node_helper_t
  skip_empty_nodes | do 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
  mhp | merging parameters
  moddata_id | module data ID (to be passed to get_module_data)
  nodename | netnode name
  valdesc | array of handler descriptions
  nvals | number of members in VALDESC
  skip_empty_nodes | do 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

  | ea | diffpos
  [out] | out | nice name

Note

See also
  get_nice_colored_name