// vim: sw=2 et /* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id: pluginreg.cpp 1502 2007-04-15 07:54:20Z itsme $ */ #include "regeval.hpp" #include "context.hpp" #include //-------------------------------------------------------------------------- // // Initialize. // // IDA will call this function only once. // If this function returns PLGUIN_SKIP, IDA will never load it again. // If this function returns PLUGIN_OK, IDA will unload the plugin but // remember that the plugin agreed to work with the database. // The plugin will be loaded again if the user invokes it by // pressing the hotkey or selecting it from the menu. // After the second load the plugin will stay on memory. // If this function returns PLUGIN_KEEP, IDA will keep the plugin // in the memory. In this case the initialization function can hook // into the processor module and user interface notification points. // See the hook_to_notification_point() function. // // In this example we check the input file format and make the decision. // You may or may not check any other conditions to decide what you do: // whether you agree to work with the database or not. // int idaapi init(void) { if ( inf.filetype == f_ELF ) return PLUGIN_SKIP; // Please uncomment the following line to see how the notification works // hook_to_notification_point(HT_UI, sample_callback, NULL); // Please uncomment the following line to see how the user-defined prefix works // set_user_defined_prefix(prefix_width, get_user_defined_prefix); return PLUGIN_KEEP; } //-------------------------------------------------------------------------- // Terminate. // Usually this callback is empty. // The plugin should unhook from the notification lists if // hook_to_notification_point() was used. // // IDA will call this function when the user asks to exit. // This function won't be called in the case of emergency exits. void idaapi term(void) { //unhook_from_notification_point(HT_UI, sample_callback); //set_user_defined_prefix(0, NULL); } bool isFunctionCall(ea_t ea) { ua_ana0(ea); return (cmd.itype==ARM_bl || cmd.itype==ARM_blx1 || cmd.itype==ARM_blx2 || cmd.itype==ARM_call); } int FindHighestParam(const char* cmt) { int n= 0; const char *p= strchr(cmt, ','); while (p) { p= strchr(p+1, ','); n++; } return n; } //-------------------------------------------------------------------------- // // The plugin method // // This is the main function of plugin. // // It will be called when the user selects the plugin. // // arg - the input argument, it can be specified in // plugins.cfg file. The default is zero. // // void idaapi run(int /*arg*/) { ea_t ea= get_screen_ea(); evalcontext_t context(ea); if (isFunctionCall(ea)) { deb(8, "isfunctioncall\n"); char *eacmt= get_cmt(ea, false); int nextparm= eacmt ? 1 + FindHighestParam(eacmt) : 0; deb(8, "highest param=%d\n", nextparm); evaltree_t *tree; if (nextparm < 4) tree= context.GetRegisterExpression(nextparm); else tree= context.GetStackVarExpression(nextparm-4); std::string newcmt= eacmt; if (newcmt.size()) newcmt += ", "; newcmt += context.EvaluateExpression(tree); set_cmt(ea, newcmt.c_str(), false); } else { for (int i=0 ; i<15 ; i++) { evaltree_t *tree= context.GetRegisterExpression(i); if (tree) { deb(8, "reg %d = %s\n", i, context.EvaluateExpression(tree).c_str()); } } } } //-------------------------------------------------------------------------- char comment[] = "Traces back register contents"; char help[] = "From the current cursor location, execution flow is traced\n" "backwards, to resolve expressions for all registers and stack variables.\n" "\n" "Type to add more evaluated function parameters to a comment.\n" "ctrl + mousewheel to display incrementally more register values.\n" "\n" "You can mark memory locations, like IO space, as volatile.\n"; //-------------------------------------------------------------------------- // This is the preferred name of the plugin module in the menu system // The preferred name may be overriden in plugins.cfg file char wanted_name[] = "Register evaluator"; // This is the preferred hotkey for the plugin module // The preferred hotkey may be overriden in plugins.cfg file // Note: IDA won't tell you if the hotkey is not correct // It will just disable the hotkey. char wanted_hotkey[] = "Alt-1"; //-------------------------------------------------------------------------- // // PLUGIN DESCRIPTION BLOCK // //-------------------------------------------------------------------------- plugin_t PLUGIN = { IDP_INTERFACE_VERSION, 0, // plugin flags init, // initialize term, // terminate. this pointer may be NULL. run, // invoke plugin comment, // long comment about the plugin // it could appear in the status line // or as a hint help, // multiline help about the plugin wanted_name, // the preferred short name of the plugin wanted_hotkey // the preferred hotkey to run the plugin };