hexrays_sample12.cpp
/*
* Hex-Rays Decompiler project
* Copyright (c) 2007-2023 by Hex-Rays, support@hex-rays.com
* ALL RIGHTS RESERVED.
*
* Sample plugin for Hex-Rays Decompiler.
* It shows a list of direct references to a register from the current
* instruction.
*/
#include <hexrays.hpp>
#include <frame.hpp>
//--------------------------------------------------------------------------
struct plugin_ctx_t : public plugmod_t
{
~plugin_ctx_t()
{
}
virtual bool idaapi run(size_t) override;
};
//--------------------------------------------------------------------------
static void collect_block_xrefs(
eavec_t *out,
mlist_t *list,
bool find_uses)
{
p = find_uses ? p->next : p->prev )
{
mlist_t &plst = find_uses ? use : def;
out->add_unique(p->ea); // this microinstruction seems to use our operand
}
}
//--------------------------------------------------------------------------
static void collect_xrefs(
eavec_t *out,
mlist_t list,
bool find_uses)
{
// first collect the references in the current block
// then find references in other blocks
if ( ch == nullptr )
return; // odd
for ( int i=0; i < ch->size(); i++ )
{
int bn = ch->at(i);
mlist_t tmp = list;
collect_block_xrefs(out, &tmp, b, ins, find_uses);
}
}
//--------------------------------------------------------------------------
static const int xwidths[] = { 3, sizeof(ea_t)*2, 60 };
static const char *const xheader[] = { "Type", "Address", "Instruction" };
struct xref_chooser_t : public chooser_t
{
const eavec_t &xrefs;
ea_t curr_ea;
int ndefs;
xref_chooser_t(
const eavec_t &v,
const char *t,
int n,
ea_t ea,
const gco_info_t &_gco)
: chooser_t(CH_MODAL|CH_KEEP, qnumber(xwidths), xwidths, xheader, t),
xrefs(v), gco(_gco), curr_ea(ea), ndefs(n)
{
}
virtual void idaapi get_row(
qstrvec_t *cols,
int *,
chooser_item_attrs_t *,
size_t n) const override
{
ea_t ea = get_ea(n);
cols->at(0) = ea == curr_ea && both ? "use/def"
: n < ndefs ? "def"
: "use";
cols->at(1).sprnt("%a", ea);
generate_disasm_line(&cols->at(2), ea, GENDSM_REMOVE_TAGS);
}
virtual ea_t idaapi get_ea(size_t n) const override
{
return xrefs[n];
}
};
//--------------------------------------------------------------------------
{
qstring title;
xref_chooser_t xc(_xrefs, title.begin(), ndefs, ea, gco);
ssize_t i = xc.choose();
if ( i >= 0 )
jumpto(_xrefs[i]);
}
//--------------------------------------------------------------------------
bool idaapi plugin_ctx_t::run(size_t)
{
ea_t ea = get_screen_ea();
func_t *pfn = get_func(ea);
if ( pfn == nullptr )
{
warning("Please position the cursor within a function");
return true;
}
flags64_t F = get_flags(ea);
if ( !is_code(F) )
{
warning("Please position the cursor on an instruction");
return true;
}
gco_info_t gco;
{
warning("Could not find a register or stkvar in the current operand");
return true;
}
// generate microcode
mba_ranges_t mbr(pfn);
if ( mba == nullptr )
{
return true;
}
{
qstring tmp;
ea_t errea = get_merror_desc(&tmp, merr, mba);
warning("%a: %s", errea, tmp.c_str());
return true;
}
// determine calling conventions without performing any optimizations
// or deleting dead code (doing so would delete an instruction that
// refers to our register and confuse the user)
// we ignore eventual errors and try to show something even if we failed
// to detect some calling conventions
if ( ncalls < 0 )
msg("%a: failed to determine some calling conventions\n", pfn->start_ea);
// prepare mlist for the current operand. we will use to to find references
// to the current operand in the microcode. usually we do not use operands
// (processor instruction operands nor microcode instruction operands)
// for searches. instead, we build a 'mlist_t' instance and use it.
mlist_t list;
{
warning("Failed to represent %s as microcode list", gco.name.c_str());
delete mba;
return false;
}
op_parent_info_t ctx;
if ( mop == nullptr )
{
warning("Could not find the operand in the microcode, sorry");
delete mba;
return false;
}
eavec_t xrefs;
int ndefs = 0;
{
// get use-def chains. do it inside a block in order to release
// the chains immediately after using them
{
// collect definitions
collect_xrefs(&xrefs, ctx, mop, list, ud, false);
ndefs = xrefs.size();
// register is used by the current instruction - add 'ea' as use-addr
xrefs.add_unique(ea);
}
if ( gco.is_def() )
{
// register is defined by the current instruction - add 'ea' as def-addr
if ( xrefs.add_unique(ea) )
ndefs = xrefs.size();
// collect using
collect_xrefs(&xrefs, ctx, mop, list, du, true);
}
// the chains will be released after quitting the block
}
show_xrefs(ea, gco, xrefs, ndefs);
// We must explicitly delete the microcode array
delete mba;
return true;
}
//--------------------------------------------------------------------------
static plugmod_t *idaapi init()
{
return nullptr; // no decompiler
msg("Hex-rays version %s has been detected, %s ready to use\n",
hxver, PLUGIN.wanted_name);
return new plugin_ctx_t;
}
//--------------------------------------------------------------------------
static const char comment[] = "Sample12 plugin for Hex-Rays decompiler";
//--------------------------------------------------------------------------
//
// PLUGIN DESCRIPTION BLOCK
//
//--------------------------------------------------------------------------
plugin_t PLUGIN =
{
IDP_INTERFACE_VERSION,
PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel
init, // initialize
nullptr,
nullptr,
comment, // long comment about the plugin
nullptr, // multiline help about the plugin
"Cross-references to register", // the preferred short name of the plugin
nullptr, // the preferred hotkey to run the plugin
};
const chain_t * get_chain(const voff_t &k, int width=1) const
Get chain for the specified value offset.
Definition: hexrays.hpp:3396
Definition: hexrays.hpp:3425
int analyze_calls(int acflags)
Analyze calls and determine calling conventions.
Definition: hexrays.hpp:11244
const mblock_t * get_mblock(int n) const
Get basic block by its serial number.
Definition: hexrays.hpp:4852
mop_t * find_mop(op_parent_info_t *ctx, ea_t ea, bool is_dest, const mlist_t &list)
Find an operand in the microcode.
Definition: hexrays.hpp:11340
mlist_t build_def_list(const minsn_t &ins, maymust_t maymust) const
Build def-list of an instruction.
Definition: hexrays.hpp:11104
mlist_t build_use_list(const minsn_t &ins, maymust_t maymust) const
Build use-list of an instruction.
Definition: hexrays.hpp:11096
HexRays SDK header file.
bool init_hexrays_plugin(int flags=0)
Check that your plugin is compatible with hex-rays decompiler.
Definition: hexrays.hpp:8548
ea_t get_merror_desc(qstring *out, merror_t code, mba_t *mba)
Get textual description of an error code.
Definition: hexrays.hpp:9747
bool get_current_operand(gco_info_t *out)
Get the instruction operand under the cursor.
Definition: hexrays.hpp:11514
mba_t * gen_microcode(const mba_ranges_t &mbr, hexrays_failure_t *hf=nullptr, const mlist_t *retlist=nullptr, int decomp_flags=0, mba_maturity_t reqmat=MMAT_GLBOPT3)
Generate microcode of an arbitrary code snippet.
Definition: hexrays.hpp:12254
bool append_to_list(mlist_t *list, const mba_t *mba) const
Append operand info to LIST.
Definition: hexrays.hpp:11508
Ranges to decompile. Either a function or an explicit vector of ranges.
Definition: hexrays.hpp:4358
Definition: hexrays.hpp:2024