Files
sigmaker-ida/idasdk76/plugins/custdata/custdata.cpp
2021-10-31 21:20:46 +02:00

178 lines
6.4 KiB
C++

/* Custom data type sample plugin.
* Copyright (c) 2010-2021 Hex-Rays, support@hex-rays.com
* Feel free to do whatever you want with this code.
*
* This sample plugin demonstates how to install a custom data type
* and a custom data format in IDA v5.7
*
* Custom data types can be used to create your own data types.
* A custom data type basically defines the data size. It can be fixed
* or variable. This plugin defines a variable size data type: a pascal
* string. Pascal strings start with a count byte:
* db len, '....'
*
* Custom data formats are used to render data values on the screen.
* Multiple data formats can be registered for a custom data type.
* The data formats with non-NULL menu_names will be listed in the 'Operand type'
* menu and the user will be able to select them.
*
*/
#include <ida.hpp>
#include <idp.hpp>
#include <struct.hpp>
#include <loader.hpp>
#include <kernwin.hpp>
struct plugin_ctx_t : public plugmod_t
{
int psid = 0; // id of the 'pascal string' data type
int psfid = 0; // id of the 'pascal string' data format
plugin_ctx_t();
~plugin_ctx_t();
virtual bool idaapi run(size_t) override { return false; }
};
//---------------------------------------------------------------------------
// We define a variable size data type. For fixed size types this function
// must be omitted.
static asize_t idaapi calc_pascal_string_length(void *, ea_t ea, asize_t maxsize)
{
if ( is_member_id(ea) )
{ // Custom data types may be used in structure definitions. If this case
// ea is a member id. Check for this situation and return 1
return 1;
}
ushort n = get_byte(ea);
if ( n+1 > maxsize )
return 0; // string would be too big
return n+1; // ok, we accept any pascal string
}
//---------------------------------------------------------------------------
// Definition of the data type
static const data_type_t pascal_string_type =
{
sizeof(data_type_t), // size of this structure
NULL, // user defined data
0, // properties
"pascal_string", // internal name of the data type
// must be unique for the current database
"Pascal string", // Menu name. If NULL, the type won't be visible in the Edit menu.
NULL, // Hotkey
"pstr", // Keyword to use in the assembly listing
2, // value size. For varsize types, specify the
// minimal size of the value
NULL, // may_create_at? NULL means the type can be created anywhere
calc_pascal_string_length, // for varsize types: calculate the exact size of an item
};
//---------------------------------------------------------------------------
// Print contents of a pascal string
static bool idaapi print_pascal_string(
void *, // user defined data, not used here
qstring *out, // output buffer. may be NULL
const void *value, // value to print. may not be NULL
asize_t size, // value size in bytes
ea_t, // current ea
int, // operand number
int) // data type id
{
const char *vptr = (const char *)value;
int n = *vptr++;
if ( n+1 > size )
return false;
if ( out != NULL )
{
*out = "\"";
for ( int i=0; i < n; i++ )
{
if ( qisprint(*vptr) )
out->append(*vptr++);
else
out->cat_sprnt("\\x%02X", uchar(*vptr++));
}
out->append('"');
}
return true;
}
//---------------------------------------------------------------------------
// Definition of the data format
static const data_format_t pascal_string_format =
{
sizeof(data_format_t), // size of this structure
NULL, // user defined data
0, // properties
"pascal_string", // internal name of the data format
NULL, // Menu name of the format. NULL means 'do not create menu item'
NULL, // Hotkey
0, // value size. 0 means that this format accepts any value size
0, // Text width of the value. Unknown, specify 0
print_pascal_string, // callback to render colored text for the data
NULL, // scan
NULL, // analyze
};
//--------------------------------------------------------------------------
static plugmod_t *idaapi init()
{
processor_t &ph = PH;
if ( ph.id != PLFM_386 )
return nullptr;
return new plugin_ctx_t;
}
//--------------------------------------------------------------------------
plugin_ctx_t::plugin_ctx_t()
{
// Register custom data type
psid = register_custom_data_type(&pascal_string_type);
// Register custom data format for it
psfid = register_custom_data_format(&pascal_string_format);
attach_custom_data_format(psid, psfid);
}
//--------------------------------------------------------------------------
plugin_ctx_t::~plugin_ctx_t()
{
// unregister data type
if ( psid > 0 )
{
// IDA would detach the data format automatically.
unregister_custom_data_type(psid);
}
// unregister data format
if ( psfid > 0 )
unregister_custom_data_format(psfid);
}
//--------------------------------------------------------------------------
//
// PLUGIN DESCRIPTION BLOCK
//
//--------------------------------------------------------------------------
plugin_t PLUGIN =
{
IDP_INTERFACE_VERSION,
PLUGIN_PROC // plugin flags
// we want the plugin to load as soon as possible
// immediately after the processor module
|PLUGIN_HIDE // we want to hide the plugin because it there will
// be a menu item in the Edit submenu
|PLUGIN_MULTI, // this plugin can work with multiple idbs in parallel
init, // initialize
nullptr,
nullptr,
"", // long comment about the plugin
// it could appear in the status line
// or as a hint
"", // multiline help about the plugin
"Sample custdata", // the preferred short name of the plugin
"" // the preferred hotkey to run the plugin
};