mirror of
https://github.com/cemu-project/idapython.git
synced 2024-12-25 17:21:53 +01:00
added Custom Viewer support
This commit is contained in:
parent
f57af01a21
commit
729084a1ff
1
build.py
1
build.py
@ -80,6 +80,7 @@ BINDIST_MANIFEST = [
|
|||||||
"examples/ex_debug_names.py",
|
"examples/ex_debug_names.py",
|
||||||
"examples/ex_graph.py",
|
"examples/ex_graph.py",
|
||||||
"examples/ex_dbg.py",
|
"examples/ex_dbg.py",
|
||||||
|
"examples/ex_custview.py",
|
||||||
"examples/ex_imports.py"
|
"examples/ex_imports.py"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
166
examples/ex_custview.py
Normal file
166
examples/ex_custview.py
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
# -----------------------------------------------------------------------
|
||||||
|
# This is an example illustrating how to use customview in Python
|
||||||
|
# (c) Hex-Rays
|
||||||
|
#
|
||||||
|
import idaapi
|
||||||
|
import idc
|
||||||
|
from idaapi import simplecustview_t
|
||||||
|
#<pycode(py_custviewex1)>
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
class mycv_t(simplecustview_t):
|
||||||
|
def Create(self, sn=None):
|
||||||
|
# Form the title
|
||||||
|
title = "Simple custom view test"
|
||||||
|
if sn:
|
||||||
|
title += " %d" % sn
|
||||||
|
# Create the customview
|
||||||
|
if not simplecustview_t.Create(self, title):
|
||||||
|
return False
|
||||||
|
id = self.AddPopupMenu("Hello")
|
||||||
|
for i in xrange(0, 100):
|
||||||
|
self.AddLine("Line %d" % i)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def OnClick(self, shift):
|
||||||
|
"""
|
||||||
|
User clicked in the view
|
||||||
|
@param shift: Shift flag
|
||||||
|
@return Boolean. True if you handled the event
|
||||||
|
"""
|
||||||
|
print "OnClick, shift=%d" % shift
|
||||||
|
return True
|
||||||
|
|
||||||
|
def OnDblClick(self, shift):
|
||||||
|
"""
|
||||||
|
User dbl-clicked in the view
|
||||||
|
@param shift: Shift flag
|
||||||
|
@return Boolean. True if you handled the event
|
||||||
|
"""
|
||||||
|
print "OnDblClick, shift=%d" % shift
|
||||||
|
return True
|
||||||
|
|
||||||
|
def OnCursorPosChanged(self):
|
||||||
|
"""
|
||||||
|
Cursor position changed.
|
||||||
|
@return Nothing
|
||||||
|
"""
|
||||||
|
print "OnCurposChanged"
|
||||||
|
|
||||||
|
def OnClose(self):
|
||||||
|
"""
|
||||||
|
The view is closing. Use this event to cleanup.
|
||||||
|
@return Nothing
|
||||||
|
"""
|
||||||
|
print "OnClose " + self.title
|
||||||
|
|
||||||
|
def OnKeydown(self, vkey, shift):
|
||||||
|
"""
|
||||||
|
User pressed a key
|
||||||
|
@param vkey: Virtual key code
|
||||||
|
@param shift: Shift flag
|
||||||
|
@return Boolean. True if you handled the event
|
||||||
|
"""
|
||||||
|
print "OnKeydown, vk=%d shift=%d" % (vkey, shift)
|
||||||
|
# ESCAPE?
|
||||||
|
if vkey == 27:
|
||||||
|
self.Close()
|
||||||
|
elif vkey == 46:
|
||||||
|
n = self.GetLineNo()
|
||||||
|
self.DelLine(n)
|
||||||
|
self.Refresh()
|
||||||
|
print "Deleted line %d" % n
|
||||||
|
# Goto?
|
||||||
|
elif vkey == ord('G'):
|
||||||
|
v = idc.AskLong(self.GetLineNo(), "Where to go?")
|
||||||
|
if v:
|
||||||
|
self.Jump(v, 0, 5)
|
||||||
|
elif vkey == ord('R'):
|
||||||
|
print "refreshing...."
|
||||||
|
self.Refresh()
|
||||||
|
elif vkey == ord('C'):
|
||||||
|
print "refreshing current line..."
|
||||||
|
self.RefreshCurrent()
|
||||||
|
elif vkey == ord('A'):
|
||||||
|
s = idc.AskStr("NewLine%d" % self.Count(), "Append new line")
|
||||||
|
self.AddLine(s)
|
||||||
|
self.Refresh()
|
||||||
|
elif vkey == ord('X'):
|
||||||
|
print "Clearing all lines"
|
||||||
|
self.ClearLines()
|
||||||
|
self.Refresh()
|
||||||
|
elif vkey == ord('I'):
|
||||||
|
n = self.GetLineNo()
|
||||||
|
s = idc.AskStr("InsertedLine%d" % n, "Insert new line")
|
||||||
|
self.InsertLine(n, s)
|
||||||
|
self.Refresh()
|
||||||
|
elif vkey == ord('E'):
|
||||||
|
l = self.GetCurrentLine(notags=1)
|
||||||
|
if not l:
|
||||||
|
return False
|
||||||
|
n = self.GetLineNo()
|
||||||
|
print "curline=<%s>" % l
|
||||||
|
l = l + idaapi.COLSTR("*", idaapi.SCOLOR_VOIDOP)
|
||||||
|
self.EditLine(n, l)
|
||||||
|
self.RefreshCurrent()
|
||||||
|
print "Edited line %d" % n
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def OnPopup(self):
|
||||||
|
"""
|
||||||
|
Context menu popup is about to be shown. Create items dynamically if you wish
|
||||||
|
@return Boolean. True if you handled the event
|
||||||
|
"""
|
||||||
|
print "OnPopup"
|
||||||
|
|
||||||
|
def OnHint(self, lineno):
|
||||||
|
"""
|
||||||
|
Hint requested for the given line number.
|
||||||
|
@param lineno: The line number (zero based)
|
||||||
|
@return:
|
||||||
|
- string: a string containing the hint
|
||||||
|
- None: if no hint available
|
||||||
|
"""
|
||||||
|
return "OnHint, line=%d" % lineno
|
||||||
|
|
||||||
|
def OnPopupMenu(self, menu_id):
|
||||||
|
"""
|
||||||
|
A context (or popup) menu item was executed.
|
||||||
|
@param menu_id: ID previously registered with add_popup_menu()
|
||||||
|
@return: Boolean
|
||||||
|
"""
|
||||||
|
print "OnPopupMenu, menu_id=%d" % menu_id
|
||||||
|
return True
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------
|
||||||
|
try:
|
||||||
|
# created already?
|
||||||
|
mycv
|
||||||
|
print "Already created, will close it..."
|
||||||
|
mycv.Close()
|
||||||
|
del mycv
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def show_win():
|
||||||
|
x = mycv_t()
|
||||||
|
if not x.Create():
|
||||||
|
print "Failed to create!"
|
||||||
|
return None
|
||||||
|
x.Show()
|
||||||
|
return x
|
||||||
|
mycv = show_win()
|
||||||
|
if not mycv:
|
||||||
|
del mycv
|
||||||
|
|
||||||
|
def make_many(n):
|
||||||
|
for i in xrange(1, n+1):
|
||||||
|
t = mycv_t()
|
||||||
|
if not t.Create(i):
|
||||||
|
break
|
||||||
|
t.Show()
|
||||||
|
return i
|
||||||
|
|
||||||
|
#</pycode(py_custviewex1)>
|
1136
swig/kernwin.i
1136
swig/kernwin.i
File diff suppressed because it is too large
Load Diff
131
swig/lines.i
131
swig/lines.i
@ -1,8 +1,7 @@
|
|||||||
// Convert this for ver 4.8 tag_remove()
|
|
||||||
%cstring_output_maxstr_none(char *buf, int bufsize);
|
|
||||||
|
|
||||||
// FIXME: These should be fixed
|
// FIXME: These should be fixed
|
||||||
|
%ignore requires_color_esc;
|
||||||
%ignore tag_on;
|
%ignore tag_on;
|
||||||
|
%ignore tag_remove;
|
||||||
%ignore tag_off;
|
%ignore tag_off;
|
||||||
%ignore tag_addchr;
|
%ignore tag_addchr;
|
||||||
%ignore tag_addstr;
|
%ignore tag_addstr;
|
||||||
@ -60,4 +59,128 @@
|
|||||||
|
|
||||||
%include "lines.hpp"
|
%include "lines.hpp"
|
||||||
|
|
||||||
%clear(char *buf, int bufsize);
|
%rename (generate_disassembly) py_generate_disassembly;
|
||||||
|
%rename (tag_remove) py_tag_remove;
|
||||||
|
%rename (tag_addr) py_tag_addr;
|
||||||
|
%rename (tag_skipcodes) py_tag_skipcodes;
|
||||||
|
%rename (tag_skipcode) py_tag_skipcode;
|
||||||
|
%rename (tag_advance) py_tag_advance;
|
||||||
|
%rename (generate_disassembly) py_generate_disassembly;
|
||||||
|
|
||||||
|
%inline
|
||||||
|
{
|
||||||
|
//<inline(py_lines)>
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
PyObject *py_tag_remove(const char *instr)
|
||||||
|
{
|
||||||
|
size_t sz = strlen(instr);
|
||||||
|
char *buf = new char[sz + 5];
|
||||||
|
if ( buf == NULL )
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
ssize_t r = tag_remove(instr, buf, sz);
|
||||||
|
PyObject *res;
|
||||||
|
if ( r < 0 )
|
||||||
|
{
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
res = Py_None;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = PyString_FromString(buf);
|
||||||
|
}
|
||||||
|
delete [] buf;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
PyObject *py_tag_addr(ea_t ea)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
tag_addr(buf, buf + sizeof(buf), ea);
|
||||||
|
return PyString_FromString(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
int py_tag_skipcode(const char *line)
|
||||||
|
{
|
||||||
|
return tag_skipcode(line)-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
int py_tag_skipcodes(const char *line)
|
||||||
|
{
|
||||||
|
return tag_skipcodes(line)-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
int py_tag_advance(const char *line, int cnt)
|
||||||
|
{
|
||||||
|
return tag_advance(line, cnt)-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
PyObject *py_generate_disassembly(ea_t ea, int max_lines, bool as_stack, bool notags)
|
||||||
|
{
|
||||||
|
if ( max_lines <= 0 )
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
|
||||||
|
qstring qbuf;
|
||||||
|
char **lines = new char *[max_lines];
|
||||||
|
int lnnum;
|
||||||
|
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
|
||||||
|
|
||||||
|
PyObject *py_tuple = PyTuple_New(nlines);
|
||||||
|
for ( int i=0; i<nlines; i++ )
|
||||||
|
{
|
||||||
|
const char *s = lines[i];
|
||||||
|
size_t line_len = strlen(s);
|
||||||
|
if ( notags )
|
||||||
|
{
|
||||||
|
qbuf.resize(line_len+5);
|
||||||
|
tag_remove(s, &qbuf[0], line_len);
|
||||||
|
s = (const char *)&qbuf[0];
|
||||||
|
}
|
||||||
|
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
|
||||||
|
qfree(lines[i]);
|
||||||
|
}
|
||||||
|
delete [] lines;
|
||||||
|
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
|
||||||
|
Py_DECREF(py_tuple);
|
||||||
|
return py_result;
|
||||||
|
}
|
||||||
|
//</inline(py_lines)>
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
%pythoncode %{
|
||||||
|
#<pycode(py_lines)>
|
||||||
|
|
||||||
|
# ---------------- Color escape sequence defitions -------------------------
|
||||||
|
COLOR_ADDR_SIZE = 16 if _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL else 8
|
||||||
|
SCOLOR_FG_MAX = '\x28' # Max color number
|
||||||
|
SCOLOR_OPND1 = chr(cvar.COLOR_ADDR+1) # Instruction operand 1
|
||||||
|
SCOLOR_OPND2 = chr(cvar.COLOR_ADDR+2) # Instruction operand 2
|
||||||
|
SCOLOR_OPND3 = chr(cvar.COLOR_ADDR+3) # Instruction operand 3
|
||||||
|
SCOLOR_OPND4 = chr(cvar.COLOR_ADDR+4) # Instruction operand 4
|
||||||
|
SCOLOR_OPND5 = chr(cvar.COLOR_ADDR+5) # Instruction operand 5
|
||||||
|
SCOLOR_OPND6 = chr(cvar.COLOR_ADDR+6) # Instruction operand 6
|
||||||
|
SCOLOR_UTF8 = chr(cvar.COLOR_ADDR+10) # Following text is UTF-8 encoded
|
||||||
|
|
||||||
|
# ---------------- Line prefix colors --------------------------------------
|
||||||
|
PALETTE_SIZE = (cvar.COLOR_FG_MAX+_idaapi.COLOR_BG_MAX)
|
||||||
|
|
||||||
|
def requires_color_esc(c):
|
||||||
|
"""
|
||||||
|
Checks if the given character requires escaping
|
||||||
|
@param c: character (string of one char)
|
||||||
|
@return: Boolean
|
||||||
|
"""
|
||||||
|
t = ord(c[0])
|
||||||
|
return c >= COLOR_ON and c <= COLOR_INV
|
||||||
|
|
||||||
|
def COLSTR(str,tag):
|
||||||
|
return SCOLOR_ON + tag + str + SCOLOR_OFF + tag
|
||||||
|
|
||||||
|
#</pycode(py_lines)>
|
||||||
|
|
||||||
|
%}
|
Loading…
Reference in New Issue
Block a user